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_prag.adb < prev    next >
Text File  |  1996-09-28  |  14KB  |  408 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                             E X P _ P R A G                              --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.24 $                             --
  10. --                                                                          --
  11. --           Copyright (c) 1992,1993,1994 NYU, All Rights Reserved          --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
  22. --                                                                          --
  23. ------------------------------------------------------------------------------
  24.  
  25. with Atree;    use Atree;
  26. with Einfo;    use Einfo;
  27. with Exp_TSS;  use Exp_TSS;
  28. with Exp_Util; use Exp_Util;
  29. with Lib;      use Lib;
  30. with Namet;    use Namet;
  31. with Nlists;   use Nlists;
  32. with Nmake;    use Nmake;
  33. with Opt;      use Opt;
  34. with Rtsfind;  use Rtsfind;
  35. with Sem;      use Sem;
  36. with Sem_Eval; use Sem_Eval;
  37. with Sem_Util; use Sem_Util;
  38. with Sinfo;    use Sinfo;
  39. with Sinput;   use Sinput;
  40. with Snames;   use Snames;
  41. with Stringt;  use Stringt;
  42. with Tbuild;   use Tbuild;
  43.  
  44. package body Exp_Prag is
  45.  
  46.    -----------------------
  47.    -- Local Subprograms --
  48.    -----------------------
  49.  
  50.    function Arg1 (N : Node_Id) return Node_Id;
  51.    function Arg2 (N : Node_Id) return Node_Id;
  52.    function Arg3 (N : Node_Id) return Node_Id;
  53.    --  Obtain specified Pragma_Argument_Association
  54.  
  55.    procedure Expand_Pragma_Abort_Defer         (N : Node_Id);
  56.    procedure Expand_Pragma_Assert              (N : Node_Id);
  57.    procedure Expand_Pragma_Convention          (N : Node_Id);
  58.    procedure Expand_Pragma_Export              (N : Node_Id);
  59.    procedure Expand_Pragma_Import              (N : Node_Id);
  60.    procedure Expand_Pragma_Interface           (N : Node_Id);
  61.    procedure Expand_Pragma_Interrupt_Priority  (N : Node_Id);
  62.  
  63.    procedure Make_Stdcall_Pragma (N : Node_Id);
  64.    --  This is used for Convention, Import, Export and Interface attributes.
  65.    --  If the convention is Stdcall, then a pragma Machine_Attribute that
  66.    --  specifies the machine attribute "stdcall" for the relevant entity is
  67.    --  constructed and inserted following the pragma being expanded.
  68.  
  69.    --------------
  70.    -- Arg1,2,3 --
  71.    --------------
  72.  
  73.    function Arg1 (N : Node_Id) return Node_Id is
  74.    begin
  75.       return First (Pragma_Argument_Associations (N));
  76.    end Arg1;
  77.  
  78.    function Arg2 (N : Node_Id) return Node_Id is
  79.    begin
  80.       return Next (Arg1 (N));
  81.    end Arg2;
  82.  
  83.    function Arg3 (N : Node_Id) return Node_Id is
  84.    begin
  85.       return Next (Arg2 (N));
  86.    end Arg3;
  87.  
  88.    ---------------------
  89.    -- Expand_N_Pragma --
  90.    ---------------------
  91.  
  92.    procedure Expand_N_Pragma (N : Node_Id) is
  93.    begin
  94.       case Get_Pragma_Id (Chars (N)) is
  95.  
  96.          --  Pragmas requiring special expander action
  97.  
  98.          when Pragma_Convention =>
  99.             Expand_Pragma_Convention (N);
  100.  
  101.          when Pragma_Abort_Defer =>
  102.             Expand_Pragma_Abort_Defer (N);
  103.  
  104.          when Pragma_Assert =>
  105.             Expand_Pragma_Assert (N);
  106.  
  107.          when Pragma_Export =>
  108.             Expand_Pragma_Export (N);
  109.  
  110.          when Pragma_Interrupt_Priority =>
  111.             Expand_Pragma_Interrupt_Priority (N);
  112.  
  113.          when Pragma_Import =>
  114.             Expand_Pragma_Import (N);
  115.  
  116.          when Pragma_Interface =>
  117.             Expand_Pragma_Interface (N);
  118.  
  119.          --  All other pragmas need no expander action
  120.  
  121.          when others => null;
  122.       end case;
  123.  
  124.    end Expand_N_Pragma;
  125.  
  126.    -------------------------------
  127.    -- Expand_Pragma_Abort_Defer --
  128.    -------------------------------
  129.  
  130.    --  An Abort_Defer pragma appears as the first statement in a handled
  131.    --  statement sequence (right after the begin). It defers aborts for
  132.    --  the entire statement sequence, but not for any declarations or
  133.    --  handlers (if any) associated with this statement sequence.
  134.  
  135.    --  With the current approach of explicit calls to Abort_Defer and
  136.    --  Abort_Undefer, we accomplish this by inserting a call to Abort_Defer
  137.    --  at the end of the associated declarations, and a call to Abort_Undefer
  138.    --  at the end of the sequence of statements. In addition, if there are
  139.    --  any exception handlers, a call to Abort_Undefer is placed at the start
  140.    --  of the statements of each of the handlers.
  141.  
  142.    procedure Expand_Pragma_Abort_Defer (N : Node_Id) is
  143.       Loc : constant Source_Ptr := Sloc (N);
  144.  
  145.       HSS : constant Node_Id := Parent (N);
  146.       --  The N_Handled_Sequence_Of_Statements node
  147.  
  148.       P : constant Node_Id := Parent (HSS);
  149.       --  The parent of the handled sequence has the declarations
  150.  
  151.       EH : Node_Id;
  152.       --  An exception handler
  153.  
  154.       Call : Node_Id;
  155.  
  156.    begin
  157.       pragma Assert (Nkind (HSS) = N_Handled_Sequence_Of_Statements);
  158.  
  159.       if No (Declarations (P)) then
  160.          Set_Declarations (P, New_List);
  161.       end if;
  162.  
  163.       Call := Build_Runtime_Call (Loc, RE_Abort_Defer);
  164.       Append (Call, Declarations (P));
  165.       Analyze (Call);
  166.       Call := Build_Runtime_Call (Loc, RE_Abort_Undefer);
  167.       Append (Call, Statements (HSS));
  168.       Analyze (Call);
  169.  
  170.       if Present (Exception_Handlers (HSS)) then
  171.          EH := First (Exception_Handlers (HSS));
  172.  
  173.          while Present (EH) loop
  174.             Call := Build_Runtime_Call (Loc, RE_Abort_Undefer);
  175.             Prepend (Call, Statements (EH));
  176.             Analyze (Call);
  177.             EH := Next (EH);
  178.          end loop;
  179.       end if;
  180.    end Expand_Pragma_Abort_Defer;
  181.  
  182.    --------------------------
  183.    -- Expand_Pragma_Assert --
  184.    --------------------------
  185.  
  186.    procedure Expand_Pragma_Assert (N : Node_Id) is
  187.       Loc : constant Source_Ptr := Sloc (N);
  188.  
  189.    begin
  190.       --  If we are not in debug mode then rewrite the pragma with
  191.       --  a null statement and do not even analyze the pragma.
  192.  
  193.       if not Assertions_Enabled then
  194.          Rewrite_Substitute_Tree (N, Make_Null_Statement (Loc));
  195.  
  196.       --  If we are in debug mode, then rewrite the pragma with its
  197.       --  corresponding if statement, and then analyze the statement
  198.       --  The expansion transforms:
  199.  
  200.       --    pragma Assert (condition [,message]);
  201.  
  202.       --  into
  203.  
  204.       --    if not condition then
  205.       --       System.Assertions.Raise_Assert_Failure (Str);
  206.       --    end if;
  207.  
  208.       --  where Str is the message if one is present, or the default of
  209.       --  file:line if no message is given.
  210.  
  211.       else
  212.          Assert : declare
  213.             Msg   : String_Id;
  214.  
  215.             procedure Store_String_Int (N : Logical_Line_Number);
  216.             --  Store characters of decimal representation of N in string
  217.             --  currently being constructed by Stringt.Store_String_Char.
  218.  
  219.             procedure Store_String_Int (N : Logical_Line_Number) is
  220.             begin
  221.                if N > 9 then
  222.                   Store_String_Int (N / 10);
  223.                end if;
  224.  
  225.                Store_String_Char
  226.                  (Get_Char_Code
  227.                    (Character'Val (N mod 10 + Character'Pos ('0'))));
  228.             end Store_String_Int;
  229.  
  230.          --  Start of processing for Assert
  231.  
  232.          begin
  233.             --  First, we need to prepare the character literal
  234.  
  235.             if Present (Arg2 (N)) then
  236.                Msg := Expr_Value_S (Expression (Arg2 (N)));
  237.  
  238.             else
  239.                Start_String;
  240.                Get_Name_String
  241.                  (Reference_Name (Source_Index (Get_Sloc_Unit_Number (Loc))));
  242.  
  243.                for J in 1 .. Name_Len loop
  244.                   Store_String_Char (Get_Char_Code (Name_Buffer (J)));
  245.                end loop;
  246.  
  247.                Store_String_Char (Get_Char_Code (':'));
  248.                Store_String_Int (Get_Line_Number (Loc));
  249.             end if;
  250.  
  251.             Store_String_Char (Get_Char_Code (Ascii.NUL));
  252.             Msg := End_String;
  253.  
  254.             --  Now generate the if statement
  255.  
  256.             Rewrite_Substitute_Tree (N,
  257.               Make_If_Statement (Loc,
  258.                 Condition =>
  259.                   Make_Op_Not (Loc,
  260.                     Right_Opnd => Expression (Arg1 (N))),
  261.                 Then_Statements => New_List (
  262.                   Make_Procedure_Call_Statement (Loc,
  263.                     Name =>
  264.                       New_Reference_To (RTE (RE_Raise_Assert_Failure), Loc),
  265.                     Parameter_Associations => New_List (
  266.                       Make_String_Literal (Loc, Msg))))));
  267.  
  268.             Analyze (N);
  269.          end Assert;
  270.       end if;
  271.  
  272.    end Expand_Pragma_Assert;
  273.  
  274.    ------------------------------
  275.    -- Expand_Pragma_Convention --
  276.    ------------------------------
  277.  
  278.    --  The only processing that is required at this stage is the possible
  279.    --  expansion of a stdcall pragma. All other processing was done during
  280.    --  the semantic analysis.
  281.  
  282.    procedure Expand_Pragma_Convention (N : Node_Id) is
  283.    begin
  284.       Make_Stdcall_Pragma (N);
  285.    end Expand_Pragma_Convention;
  286.  
  287.    --------------------------
  288.    -- Expand_Pragma_Export --
  289.    --------------------------
  290.  
  291.    --  The only processing that is required at this stage is the possible
  292.    --  expansion of a stdcall pragma. All other processing was done during
  293.    --  the semantic analysis.
  294.  
  295.    procedure Expand_Pragma_Export (N : Node_Id) is
  296.    begin
  297.       Make_Stdcall_Pragma (N);
  298.    end Expand_Pragma_Export;
  299.    --------------------------
  300.    -- Expand_Pragma_Import --
  301.    --------------------------
  302.  
  303.    --  When applied to a variable, the default initialization must not be
  304.    --  done. As it is already done when the pragma is found, we just get rid
  305.    --  of the call the initialization procedure which followed the object
  306.    --  declaration.
  307.  
  308.    --  We can't use the freezing mechanism for this purpose, since we
  309.    --  have to elaborate the initialization expression when it is first
  310.    --  seen (i.e. this elaboration cannot be deferred to the freeze point).
  311.  
  312.    procedure Expand_Pragma_Import (N : Node_Id) is
  313.       Def_Id    : constant Entity_Id := Entity (Expression (Arg2 (N)));
  314.       Init      : Entity_Id;
  315.       After_Def : Node_Id;
  316.  
  317.    begin
  318.       Make_Stdcall_Pragma (N);
  319.  
  320.       if Ekind (Def_Id) = E_Variable then
  321.          Init := Base_Init_Proc (Etype (Def_Id));
  322.          After_Def := Next (Parent (Def_Id));
  323.  
  324.          if Present (Init)
  325.            and then Nkind (After_Def) = N_Procedure_Call_Statement
  326.            and then Is_Entity_Name (Name (After_Def))
  327.            and then Entity (Name (After_Def)) = Init
  328.          then
  329.             Remove (After_Def);
  330.  
  331.          elsif Is_Access_Type (Etype (Def_Id)) then
  332.             Set_Expression (Parent (Def_Id), Empty);
  333.          end if;
  334.       end if;
  335.    end Expand_Pragma_Import;
  336.  
  337.    -----------------------------
  338.    -- Expand_Pragma_Interface --
  339.    -----------------------------
  340.  
  341.    --  The only processing that is required at this stage is the possible
  342.    --  expansion of a stdcall pragma. All other processing was done during
  343.    --  the semantic analysis.
  344.  
  345.    procedure Expand_Pragma_Interface (N : Node_Id) is
  346.    begin
  347.       Make_Stdcall_Pragma (N);
  348.    end Expand_Pragma_Interface;
  349.  
  350.    --------------------------------------
  351.    -- Expand_Pragma_Interrupt_Priority --
  352.    --------------------------------------
  353.  
  354.    --  Supply default argument if none exists (System.Interrupt_Priority'Last)
  355.  
  356.    procedure Expand_Pragma_Interrupt_Priority (N : Node_Id) is
  357.    begin
  358.       if No (Pragma_Argument_Associations (N)) then
  359.          Set_Pragma_Argument_Associations (N, New_List (
  360.            Make_Pragma_Argument_Association (Sloc (N),
  361.              Expression =>
  362.                Make_Attribute_Reference (Sloc (N),
  363.                  Prefix => RTE (RE_Interrupt_Priority),
  364.                  Attribute_Name => Name_Last))));
  365.       end if;
  366.    end Expand_Pragma_Interrupt_Priority;
  367.  
  368.    -------------------------
  369.    -- Make_Stdcall_Pragma --
  370.    -------------------------
  371.  
  372.    procedure Make_Stdcall_Pragma (N : Node_Id) is
  373.       Stdcall : String_Id;
  374.  
  375.    begin
  376.       if Chars (Expression (Arg1 (N))) = Name_Stdcall then
  377.          Start_String;
  378.          Store_String_Chars ("stdcall");
  379.          Stdcall := End_String;
  380.  
  381.          --  Now construct the pragma:
  382.  
  383.          --    pragma Machine_Attribute
  384.          --      (Attribute_Name => "stdcall", Entity => xxx);
  385.  
  386.          --  where xxx is the entity from the Convention, Import, Export
  387.          --  pragma which caused this procedure to be called, and insert
  388.          --  this pragma immediately after the parent pragma.
  389.  
  390.          Insert_After (N,
  391.            Make_Pragma (Sloc (N),
  392.              Chars => Name_Machine_Attribute,
  393.              Pragma_Argument_Associations => New_List (
  394.                Make_Pragma_Argument_Association (Sloc (N),
  395.                  Chars => Name_Attribute_Name,
  396.                  Expression =>
  397.                    Make_String_Literal (Sloc (N), Stdcall)),
  398.  
  399.                Make_Pragma_Argument_Association (Sloc (N),
  400.                  Chars => Name_Entity,
  401.                  Expression =>
  402.                    Make_Identifier (Sloc (N),
  403.                      Chars => Chars (Expression (Arg2 (N))))))));
  404.       end if;
  405.    end Make_Stdcall_Pragma;
  406.  
  407. end Exp_Prag;
  408.