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_fixd.adb < prev    next >
Text File  |  1996-09-28  |  80KB  |  2,262 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                             E X P _ F I X D                              --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.38 $                             --
  10. --                                                                          --
  11. --        Copyright (c) 1992,1993,1994,1995 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 Treepr;   use Treepr;
  26. with Atree;    use Atree;
  27. with Einfo;    use Einfo;
  28. with Nlists;   use Nlists;
  29. with Nmake;    use Nmake;
  30. with Output;   use Output;
  31. with Rtsfind;  use Rtsfind;
  32. with Sem;      use Sem;
  33. with Sem_Res;  use Sem_Res;
  34. with Sem_Util; use Sem_Util;
  35. with Sinfo;    use Sinfo;
  36. with Stand;    use Stand;
  37. with Tbuild;   use Tbuild;
  38. with Uintp;    use Uintp;
  39. with Urealp;   use Urealp;
  40.  
  41. package body Exp_Fixd is
  42.  
  43.    ------------------------
  44.    --  Local Subprograms --
  45.    ------------------------
  46.  
  47.    --  General note; in this unit, a number of routines are driven by the
  48.    --  types (Etype) of their operands. Since we are dealing with unanalyzed
  49.    --  expressions as they are constructed, the Etypes would not normally be
  50.    --  set, but the construction routines that we use in this unit do in fact
  51.    --  set the Etype values correctly. In addition, setting the Etype ensures
  52.    --  that the analyzer does not try to redetermine the type when the node
  53.    --  is analyzed (which would be wrong, since in the case where we set the
  54.    --  Treat_Fixed_As_Integer or Conversion_OK flags, it would think it was
  55.    --  still dealing with a normal fixed-point operation and mess it up).
  56.  
  57.    function Build_Conversion
  58.      (N    : Node_Id;
  59.       Typ  : Entity_Id;
  60.       Expr : Node_Id)
  61.       return Node_Id;
  62.    --  Build an expression that convers the expression Expr to type Typ,
  63.    --  taking the source location from Sloc (N). If the conversions involve
  64.    --  fixed-point types, then the Conversion_OK flag will be set so that the
  65.    --  resulting conversions do not get re-expanded. On return the resulting
  66.    --  node has its Etype set.
  67.  
  68.    function Build_Divide (N : Node_Id; L, R : Node_Id) return Node_Id;
  69.    --  Builds an N_Op_Divide node from the given left and right operand
  70.    --  expressions, using the source location from Sloc (N). The operands
  71.    --  are either both Long_Long_Float, in which case Build_Divide differs
  72.    --  from Make_Op_Divide only in that the Etype of the resulting node is
  73.    --  set (to Long_Long_Float), or they can be integer types. In this case
  74.    --  the integer types need not be the same, and Build_Divide converts
  75.    --  the operand with the smaller sized type to match the type of the
  76.    --  other operand and sets this as the result type. The Rounded_Result
  77.    --  flag of the result in this case is set from the Rounded_Result flag
  78.    --  of node N. On return, the resulting node is analyzed, and has its
  79.    --  Etype set.
  80.  
  81.    function Build_Double_Divide
  82.      (N       : Node_Id;
  83.       X, Y, Z : Node_Id)
  84.       return    Node_Id;
  85.    --  Returns a node corresponding to the value X/(Y*Z) using the source
  86.    --  location from Sloc (N). The division is rounded if the Rounded_Result
  87.    --  flag of N is set. The integer types of X, Y, Z may be different. On
  88.    --  return the resulting node is analyzed, and has its Etype set.
  89.  
  90.    procedure Build_Double_Divide_Code
  91.      (N        : Node_Id;
  92.       X, Y, Z  : Node_Id;
  93.       Qnn, Rnn : out Entity_Id;
  94.       Code     : out List_Id);
  95.    --  Generates a sequence of code for determining the quotient and remainder
  96.    --  of the division X/(Y*Z), using the source location from Sloc (N).
  97.    --  Entities of appropriate types are allocated for the quotient and
  98.    --  remainder and returned in Qnn and Rnn. The result is rounded if
  99.    --  the Rounded_Result flag of N is set. The Etype fields of Qnn and Rnn
  100.    --  are appropriately set on return.
  101.  
  102.    function Build_Multiply (N : Node_Id; L, R : Node_Id) return Node_Id;
  103.    --  Builds an N_Op_Multiply node from the given left and right operand
  104.    --  expressions, using the source location from Sloc (N). The operands
  105.    --  are either both Long_Long_Float, in which case Build_Divide differs
  106.    --  from Make_Op_Multiply only in that the Etype of the resulting node is
  107.    --  set (to Long_Long_Float), or they can be integer types. In this case
  108.    --  the integer types need not be the same, and Build_Multiply chooses
  109.    --  a type long enough to hold the product (i.e. twice the size of the
  110.    --  longer of the two operand types), and both operands are converted
  111.    --  to this type. The Etype of the result is also set to this value.
  112.    --  However, the result can never overflow Integer_64, so this is the
  113.    --  largest type that is ever generated. On return, the resulting node
  114.    --  is analyzed and has its Etype set.
  115.  
  116.    function Build_Rem (N : Node_Id; L, R : Node_Id) return Node_Id;
  117.    --  Builds an N_Op_Rem node from the given left and right operand
  118.    --  expressions, using the source location from Sloc (N). The operands
  119.    --  are both integer types, which need not be the same. Build_Rem
  120.    --  converts the operand with the smaller sized type to match the type
  121.    --  of the other operand and sets this as the result type. The result
  122.    --  is never rounded (rem operations cannot be rounded in any case!)
  123.    --  On return, the resulting node is analyzed and has its Etype set.
  124.  
  125.    function Build_Scaled_Divide
  126.      (N       : Node_Id;
  127.       X, Y, Z : Node_Id)
  128.       return    Node_Id;
  129.    --  Returns a node corresponding to the value X*Y/Z using the source
  130.    --  location from Sloc (N). The division is rounded if the Rounded_Result
  131.    --  flag of N is set. The integer types of X, Y, Z may be different. On
  132.    --  return the resulting node is analyzed and has is Etype set.
  133.  
  134.    procedure Build_Scaled_Divide_Code
  135.      (N        : Node_Id;
  136.       X, Y, Z  : Node_Id;
  137.       Qnn, Rnn : out Entity_Id;
  138.       Code     : out List_Id);
  139.    --  Generates a sequence of code for determining the quotient and remainder
  140.    --  of the division X*Y/Z, using the source location from Sloc (N). Entities
  141.    --  of appropriate types are allocated for the quotient and remainder and
  142.    --  returned in Qnn and Rrr. The integer types for X, Y, Z may be different.
  143.    --  The division is rounded if the Rounded_Result flag of N is set. The
  144.    --  Etype fields of Qnn and Rnn are appropriately set on return.
  145.  
  146.    procedure Do_Divide_Fixed_Fixed (N : Node_Id);
  147.    --  Handles expansion of divide for case of two fixed-point operands
  148.    --  (neither of them universal), with an integer or fixed-point result.
  149.    --  N is the N_Op_Divide node to be expanded.
  150.  
  151.    procedure Do_Divide_Fixed_Universal (N : Node_Id);
  152.    --  Handles expansion of divide for case of a fixed-point operand divided
  153.    --  by a universal real operand, with an integer or fixed-point result. N
  154.    --  is the N_Op_Divide node to be expanded.
  155.  
  156.    procedure Do_Divide_Universal_Fixed (N : Node_Id);
  157.    --  Handles expansion of divide for case of a universal real operand
  158.    --  divided by a fixed-point operand, with an integer or fixed-point
  159.    --  result. N is the N_Op_Divide node to be expanded.
  160.  
  161.    procedure Do_Multiply_Fixed_Fixed (N : Node_Id);
  162.    --  Handles expansion of multiply for case of two fixed-point operands
  163.    --  (neither of them universal), with an integer or fixed-point result.
  164.    --  N is the N_Op_Multiply node to be expanded.
  165.  
  166.    procedure Do_Multiply_Fixed_Universal (N : Node_Id; Left, Right : Node_Id);
  167.    --  Handles expansion of multiply for case of a fixed-point operand
  168.    --  multiplied by a universal real operand, with an integer or fixed-
  169.    --  point result. N is the N_Op_Multiply node to be expanded, and
  170.    --  Left, Right are the operands (which may have been switched).
  171.  
  172.    function Fpt_Value (N : Node_Id) return Node_Id;
  173.    --  Given an operand of fixed-point operation, return an expression that
  174.    --  represents the corresponding Long_Long_Float value. The expression
  175.    --  can be of integer type, floating-point type, or fixed-point type.
  176.    --  The expression returned is neither analyzed and resolved. The Etype
  177.    --  of the result is properly set (to Long_Long_Float).
  178.  
  179.    function Integer_Literal (N : Node_Id; V : Uint) return Node_Id;
  180.    --  Given a non-negative universal integer value, build a typed integer
  181.    --  literal node, using the smallest applicable standard integer type. If
  182.    --  the value exceeds 2**63-1, the largest value allowed for perfect result
  183.    --  set scaling factors (see RM G.2.3(22)), then Empty is returned. The
  184.    --  node N provides the Sloc value for the constructed literal. The Etype
  185.    --  of the resulting literal is correctly set, and it is marked as analyzed.
  186.  
  187.    function Real_Literal (N : Node_Id; V : Ureal) return Node_Id;
  188.    --  Build a real literal node from the given value, the Etype of the
  189.    --  returned node is set to Long_Long_Float, since all floating-point
  190.    --  arithmetic operations that we construct use Long_Long_Float
  191.  
  192.    function Rounded_Result_Set (N : Node_Id) return Boolean;
  193.    --  Returns True if N is a node that contains the Rounded_Result flag
  194.    --  and if the flag is true.
  195.  
  196.    procedure Set_Result (N : Node_Id; Expr : Node_Id);
  197.    --  N is the node for the current conversion, division or multiplication
  198.    --  operation, and Expr is an expression representing the result. Expr
  199.    --  may be of floating-point or integer type. If the operation result
  200.    --  is fixed-point, then the value of Expr is in units of small of the
  201.    --  result type (i.e. small's have already been dealt with). The result
  202.    --  of the call is to replace N by an appropriate conversion to the
  203.    --  result type, dealing with rounding for the decimal types case. The
  204.    --  node is then analyzed and resolved using the result type.
  205.  
  206.    ----------------------
  207.    -- Build_Conversion --
  208.    ----------------------
  209.  
  210.    function Build_Conversion
  211.      (N    : Node_Id;
  212.       Typ  : Entity_Id;
  213.       Expr : Node_Id)
  214.       return Node_Id
  215.    is
  216.       Loc    : constant Source_Ptr := Sloc (N);
  217.       Extyp  : constant Entity_Id  := Etype (Expr);
  218.       Result : Node_Id;
  219.       Intyp  : Entity_Id;
  220.  
  221.    begin
  222.       --  Remove inner conversion if both inner and outer conversions are to
  223.       --  integer types, since the inner one serves no purpose (except perhaps
  224.       --  to guarantee rounding, so we preserve the Rounded_Result flag)
  225.  
  226.       if Is_Integer_Type (Typ)
  227.         and then Is_Integer_Type (Extyp)
  228.         and then Nkind (Expr) = N_Type_Conversion
  229.       then
  230.          Result :=
  231.            Make_Type_Conversion (Loc,
  232.              Subtype_Mark => New_Occurrence_Of (Typ, Loc),
  233.              Expression   => Expression (Expr));
  234.          Set_Rounded_Result (Result, Rounded_Result_Set (Expr));
  235.  
  236.       --  Another special case, if the expression is an integer literal
  237.       --  and the target type is an integer type or fixed-oint type, then
  238.       --  just retype the integer literal to the desired target type.
  239.  
  240.       elsif Nkind (Expr) = N_Integer_Literal
  241.         and then (Is_Integer_Type (Typ) or else Is_Fixed_Point_Type (Typ))
  242.       then
  243.          Result := Expr;
  244.  
  245.       --  For all other cases, a simple type conversion will work
  246.  
  247.       else
  248.          Result :=
  249.            Make_Type_Conversion (Loc,
  250.              Subtype_Mark => New_Occurrence_Of (Typ, Loc),
  251.              Expression   => Expr);
  252.  
  253.          --  Set Conversion_OK if either result or expression type is a
  254.          --  fixed-point type, since from a semantic point of view, we are
  255.          --  treating fixed-point values as integers at this stage.
  256.  
  257.          if Is_Fixed_Point_Type (Typ)
  258.            or else Is_Fixed_Point_Type (Extyp)
  259.          then
  260.             Set_Conversion_OK (Result);
  261.          end if;
  262.       end if;
  263.  
  264.       Set_Etype (Result, Typ);
  265.       return Result;
  266.  
  267.    end Build_Conversion;
  268.  
  269.    ------------------
  270.    -- Build_Divide --
  271.    ------------------
  272.  
  273.    function Build_Divide (N : Node_Id; L, R : Node_Id) return Node_Id is
  274.       Loc         : constant Source_Ptr := Sloc (N);
  275.       Left_Type   : constant Entity_Id  := Etype (L);
  276.       Right_Type  : constant Entity_Id  := Etype (R);
  277.       Result_Type : Entity_Id;
  278.       Rnode       : Node_Id;
  279.  
  280.    begin
  281.       --  Deal with floating-point case first
  282.  
  283.       if Is_Floating_Point_Type (Left_Type) then
  284.          pragma Assert (Left_Type = Standard_Long_Long_Float);
  285.          pragma Assert (Right_Type = Standard_Long_Long_Float);
  286.  
  287.          Rnode := Make_Op_Divide (Loc, L, R);
  288.          Result_Type := Standard_Long_Long_Float;
  289.  
  290.       --  Integer and fixed-point cases
  291.  
  292.       else
  293.          --  An optimization. If the right operand is the literal 1, then we
  294.          --  can just return the right hand operand. Putting the optimization
  295.          --  here allows us to omit the check at the call site.
  296.  
  297.          if Nkind (R) = N_Integer_Literal and then Intval (R) = 1 then
  298.             return L;
  299.          end if;
  300.  
  301.          --  If left and right types are the same, no conversion needed
  302.  
  303.          if Left_Type = Right_Type then
  304.             Result_Type := Left_Type;
  305.             Rnode :=
  306.               Make_Op_Divide (Loc,
  307.                 Left_Opnd  => L,
  308.                 Right_Opnd => R);
  309.  
  310.          --  Use left type if is is the larger of the two
  311.  
  312.          elsif Esize (Left_Type) >= Esize (Right_Type) then
  313.             Result_Type := Left_Type;
  314.             Rnode :=
  315.               Make_Op_Divide (Loc,
  316.                 Left_Opnd  => L,
  317.                 Right_Opnd => Build_Conversion (N, Left_Type, R));
  318.  
  319.          --  Otherwise right type is larger of the two, us it
  320.  
  321.          else
  322.             Result_Type := Right_Type;
  323.             Rnode :=
  324.               Make_Op_Divide (Loc,
  325.                 Left_Opnd => Build_Conversion (N, Right_Type, L),
  326.                 Right_Opnd => R);
  327.          end if;
  328.       end if;
  329.  
  330.       --  We now have a divide node built with Result_Type set. First
  331.       --  set Etype of result, as required for all Build_xxx routines
  332.  
  333.       Set_Etype (Rnode, Base_Type (Result_Type));
  334.  
  335.       --  Set Treat_Fixed_As_Integer if operation on fixed-point type
  336.       --  since this is a literal arithmetic operation, to be performed
  337.       --  by Gigi without any consideration of small values.
  338.  
  339.       if Is_Fixed_Point_Type (Result_Type) then
  340.          Set_Treat_Fixed_As_Integer (Rnode);
  341.       end if;
  342.  
  343.       --  The result is rounded if the target of the operation is decimal
  344.       --  and Rounded_Result is set, or if the target of the operation
  345.       --  is an integer type.
  346.  
  347.       if Is_Integer_Type (Etype (N))
  348.         or else Rounded_Result_Set (N)
  349.       then
  350.          Set_Rounded_Result (Rnode);
  351.       end if;
  352.  
  353.       return Rnode;
  354.  
  355.    end Build_Divide;
  356.  
  357.    -------------------------
  358.    -- Build_Double_Divide --
  359.    -------------------------
  360.  
  361.    function Build_Double_Divide
  362.      (N       : Node_Id;
  363.       X, Y, Z : Node_Id)
  364.       return    Node_Id
  365.    is
  366.       Y_Size : constant Int := UI_To_Int (Esize (Etype (Y)));
  367.       Z_Size : constant Int := UI_To_Int (Esize (Etype (Z)));
  368.       Expr   : Node_Id;
  369.  
  370.    begin
  371.       --  If denominator fits in 64 bits, we can build the operations directly
  372.       --  without causing any intermediate overflow, so that's what we do!
  373.  
  374.       if Int'Max (Y_Size, Z_Size) <= 32 then
  375.          return
  376.            Build_Divide (N, X, Build_Multiply (N, Y, Z));
  377.  
  378.       --  Otherwise we use the runtime routine
  379.  
  380.       --    [Qnn : Interfaces.Integer_64,
  381.       --     Rnn : Interfaces.Integer_64;
  382.       --     Double_Divide (X, Y, Z, Qnn, Rnn, Round);
  383.       --     Qnn]
  384.  
  385.       else
  386.          declare
  387.             Loc  : constant Source_Ptr := Sloc (N);
  388.             Qnn  : Entity_Id;
  389.             Rnn  : Entity_Id;
  390.             Code : List_Id;
  391.  
  392.          begin
  393.             Build_Double_Divide_Code (N, X, Y, Z, Qnn, Rnn, Code);
  394.             Expr :=
  395.               Make_Expression_Actions (Loc,
  396.                 Actions    => Code,
  397.                 Expression => New_Occurrence_Of (Qnn, Loc));
  398.  
  399.             --  Set type of result in case used elsewhere (see note at start)
  400.  
  401.             Set_Etype (Expr, Etype (Qnn));
  402.  
  403.             --  Set result as analyzed (see note at start on build routines)
  404.  
  405.             return Expr;
  406.          end;
  407.       end if;
  408.    end Build_Double_Divide;
  409.  
  410.    ------------------------------
  411.    -- Build_Double_Divide_Code --
  412.    ------------------------------
  413.  
  414.    --  If the denominator can be computed in 64-bits, we build
  415.  
  416.    --    [Nnn : constant typ := typ (X);
  417.    --     Dnn : constant typ := typ (Y) * typ (Z)
  418.    --     Qnn : constant typ := Nnn / Dnn;
  419.    --     Rnn : constant typ := Nnn / Dnn;
  420.  
  421.    --  If the numerator cannot be computed in 64 bits, we build
  422.  
  423.    --    [Qnn : typ;
  424.    --     Rnn : typ;
  425.    --     Double_Divide (X, Y, Z, Qnn, Rnn, Round);]
  426.  
  427.    procedure Build_Double_Divide_Code
  428.      (N        : Node_Id;
  429.       X, Y, Z  : Node_Id;
  430.       Qnn, Rnn : out Entity_Id;
  431.       Code     : out List_Id)
  432.    is
  433.       Loc    : constant Source_Ptr := Sloc (N);
  434.  
  435.       X_Size : constant Int := UI_To_Int (Esize (Etype (X)));
  436.       Y_Size : constant Int := UI_To_Int (Esize (Etype (Y)));
  437.       Z_Size : constant Int := UI_To_Int (Esize (Etype (Z)));
  438.  
  439.       QR_Siz : Int;
  440.       QR_Typ : Entity_Id;
  441.  
  442.       Nnn : Entity_Id;
  443.       Dnn : Entity_Id;
  444.  
  445.       Quo : Node_Id;
  446.       Rnd : Entity_Id;
  447.  
  448.    begin
  449.       --  Find type that will allow computation of numerator
  450.  
  451.       QR_Siz := Int'Max (X_Size, 2 * Int'Max (Y_Size, Z_Size));
  452.  
  453.       if QR_Siz <= 16 then
  454.          QR_Typ := Standard_Integer_16;
  455.       elsif QR_Siz <= 32 then
  456.          QR_Typ := Standard_Integer_32;
  457.       elsif QR_Siz <= 64 then
  458.          QR_Typ := Standard_Integer_64;
  459.  
  460.       --  For more than 64, bits, we use the 64-bit integer defined in
  461.       --  Interfaces, so that it can be handled by the runtime routine
  462.  
  463.       else
  464.          QR_Typ := RTE (RE_Integer_64);
  465.       end if;
  466.  
  467.       --  Define quotient and remainder, and set their Etypes, so
  468.       --  that they can be picked up by Build_xxx routines.
  469.  
  470.       Qnn := Make_Defining_Identifier (Loc, New_Internal_Name ('S'));
  471.       Rnn := Make_Defining_Identifier (Loc, New_Internal_Name ('R'));
  472.  
  473.       Set_Etype (Qnn, QR_Typ);
  474.       Set_Etype (Rnn, QR_Typ);
  475.  
  476.       --  Case that we can compute the denominator in 64 bits
  477.  
  478.       if QR_Siz <= 64 then
  479.  
  480.          --  Create temporaries for numerator and denominator and set Etypes,
  481.          --  so that New_Occurrence_Of picks them up for Build_xxx calls.
  482.  
  483.          Nnn := Make_Defining_Identifier (Loc, New_Internal_Name ('N'));
  484.          Dnn := Make_Defining_Identifier (Loc, New_Internal_Name ('D'));
  485.  
  486.          Set_Etype (Nnn, QR_Typ);
  487.          Set_Etype (Dnn, QR_Typ);
  488.  
  489.          Code := New_List (
  490.            Make_Object_Declaration (Loc,
  491.              Defining_Identifier => Nnn,
  492.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc),
  493.              Constant_Present    => True,
  494.              Expression => Build_Conversion (N, QR_Typ, X)),
  495.  
  496.            Make_Object_Declaration (Loc,
  497.              Defining_Identifier => Dnn,
  498.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc),
  499.              Constant_Present    => True,
  500.              Expression =>
  501.                Build_Multiply (N,
  502.                  Build_Conversion (N, QR_Typ, Y),
  503.                  Build_Conversion (N, QR_Typ, Z))));
  504.  
  505.          Quo :=
  506.            Build_Divide (N,
  507.              New_Occurrence_Of (Nnn, Loc),
  508.              New_Occurrence_Of (Dnn, Loc));
  509.  
  510.          Set_Rounded_Result (Quo, Rounded_Result_Set (N));
  511.  
  512.          Append_To (Code,
  513.            Make_Object_Declaration (Loc,
  514.              Defining_Identifier => Qnn,
  515.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc),
  516.              Constant_Present    => True,
  517.              Expression          => Quo));
  518.  
  519.          Append_To (Code,
  520.            Make_Object_Declaration (Loc,
  521.              Defining_Identifier => Rnn,
  522.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc),
  523.              Constant_Present    => True,
  524.              Expression =>
  525.                Build_Rem (N,
  526.                  New_Occurrence_Of (Nnn, Loc),
  527.                  New_Occurrence_Of (Dnn, Loc))));
  528.  
  529.       --  Case where denominator does not fit in 64 bits, so we have to
  530.       --  call the runtime routine to compute the quotient and remainder
  531.  
  532.       else
  533.          if Rounded_Result_Set (N) then
  534.             Rnd := Standard_True;
  535.          else
  536.             Rnd := Standard_False;
  537.          end if;
  538.  
  539.          Code := New_List (
  540.            Make_Object_Declaration (Loc,
  541.              Defining_Identifier => Qnn,
  542.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc)),
  543.  
  544.            Make_Object_Declaration (Loc,
  545.              Defining_Identifier => Rnn,
  546.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc)),
  547.  
  548.            Make_Procedure_Call_Statement (Loc,
  549.              Name => New_Occurrence_Of (RTE (RE_Double_Divide), Loc),
  550.              Parameter_Associations => New_List (
  551.                Build_Conversion (N, QR_Typ, X),
  552.                Build_Conversion (N, QR_Typ, Y),
  553.                Build_Conversion (N, QR_Typ, Z),
  554.                New_Occurrence_Of (Qnn, Loc),
  555.                New_Occurrence_Of (Rnn, Loc),
  556.                New_Occurrence_Of (Rnd, Loc))));
  557.       end if;
  558.  
  559.    end Build_Double_Divide_Code;
  560.  
  561.    --------------------
  562.    -- Build_Multiply --
  563.    --------------------
  564.  
  565.    function Build_Multiply (N : Node_Id; L, R : Node_Id) return Node_Id is
  566.       Loc         : constant Source_Ptr := Sloc (N);
  567.       Left_Type   : constant Entity_Id  := Etype (L);
  568.       Right_Type  : constant Entity_Id  := Etype (R);
  569.       Rsize       : Int;
  570.       Result_Type : Entity_Id;
  571.       Rnode       : Node_Id;
  572.  
  573.    begin
  574.       --  Deal with floating-point case first
  575.  
  576.       if Is_Floating_Point_Type (Left_Type) then
  577.          pragma Assert (Left_Type = Standard_Long_Long_Float);
  578.          pragma Assert (Right_Type = Standard_Long_Long_Float);
  579.  
  580.          Result_Type := Standard_Long_Long_Float;
  581.          Rnode := Make_Op_Multiply (Loc, L, R);
  582.  
  583.       --  Integer and fixed-point cases
  584.  
  585.       else
  586.          --  An optimization. If the right operand is the literal 1, then we
  587.          --  can just return the left hand operand. Putting the optimization
  588.          --  here allows us to omit the check at the call site. Similarly, if
  589.          --  the left operand is the integer 1 we can return the right operand.
  590.  
  591.          if Nkind (R) = N_Integer_Literal and then Intval (R) = 1 then
  592.             return L;
  593.          elsif Nkind (L) = N_Integer_Literal and then Intval (L) = 1 then
  594.             return R;
  595.          end if;
  596.  
  597.          --  Otherwise we use a type that is at least twice the longer
  598.          --  of the two sizes.
  599.  
  600.          Rsize := 2 * Int'Max (UI_To_Int (Esize (Left_Type)),
  601.                                UI_To_Int (Esize (Right_Type)));
  602.  
  603.          if Rsize <= 8 then
  604.             Result_Type := Standard_Integer_8;
  605.  
  606.          elsif Rsize <= 16 then
  607.             Result_Type := Standard_Integer_16;
  608.  
  609.          elsif Rsize <= 32 then
  610.             Result_Type := Standard_Integer_32;
  611.  
  612.          else
  613.             Result_Type := Standard_Integer_64;
  614.          end if;
  615.  
  616.          Rnode :=
  617.             Make_Op_Multiply (Loc,
  618.               Left_Opnd  => Build_Conversion (N, Result_Type, L),
  619.               Right_Opnd => Build_Conversion (N, Result_Type, R));
  620.       end if;
  621.  
  622.       --  We now have a multiply node built with Result_Type set. First
  623.       --  set Etype of result, as required for all Build_xxx routines
  624.  
  625.       Set_Etype (Rnode, Base_Type (Result_Type));
  626.  
  627.       --  Set Treat_Fixed_As_Integer if operation on fixed-point type
  628.       --  since this is a literal arithmetic operation, to be performed
  629.       --  by Gigi without any consideration of small values.
  630.  
  631.       if Is_Fixed_Point_Type (Result_Type) then
  632.          Set_Treat_Fixed_As_Integer (Rnode);
  633.       end if;
  634.  
  635.       return Rnode;
  636.    end Build_Multiply;
  637.  
  638.    ---------------
  639.    -- Build_Rem --
  640.    ---------------
  641.  
  642.    function Build_Rem (N : Node_Id; L, R : Node_Id) return Node_Id is
  643.       Loc         : constant Source_Ptr := Sloc (N);
  644.       Left_Type   : constant Entity_Id  := Etype (L);
  645.       Right_Type  : constant Entity_Id  := Etype (R);
  646.       Result_Type : Entity_Id;
  647.       Rnode       : Node_Id;
  648.  
  649.    begin
  650.       if Left_Type = Right_Type then
  651.          Result_Type := Left_Type;
  652.          Rnode :=
  653.            Make_Op_Rem (Loc,
  654.              Left_Opnd  => L,
  655.              Right_Opnd => R);
  656.  
  657.       --  If left size is larger, we do the remainder operation using the
  658.       --  size of the left type (i.e. the larger of the two integer types).
  659.  
  660.       elsif Esize (Left_Type) >= Esize (Right_Type) then
  661.          Result_Type := Left_Type;
  662.          Rnode :=
  663.            Make_Op_Rem (Loc,
  664.              Left_Opnd  => L,
  665.              Right_Opnd => Build_Conversion (N, Left_Type, R));
  666.  
  667.       --  Similarly, if the right size is larger, we do the remainder
  668.       --  operation using the right type.
  669.  
  670.       else
  671.          Result_Type := Right_Type;
  672.          Rnode :=
  673.            Make_Op_Rem (Loc,
  674.              Left_Opnd => Build_Conversion (N, Right_Type, L),
  675.              Right_Opnd => R);
  676.       end if;
  677.  
  678.       --  We now have an N_Op_Rem node built with Result_Type set. First
  679.       --  set Etype of result, as required for all Build_xxx routines
  680.  
  681.       Set_Etype (Rnode, Base_Type (Result_Type));
  682.  
  683.       --  Set Treat_Fixed_As_Integer if operation on fixed-point type
  684.       --  since this is a literal arithmetic operation, to be performed
  685.       --  by Gigi without any consideration of small values.
  686.  
  687.       if Is_Fixed_Point_Type (Result_Type) then
  688.          Set_Treat_Fixed_As_Integer (Rnode);
  689.       end if;
  690.  
  691.       --  One more check. We did the rem operation using the larger of the
  692.       --  two types, which is reasonable. However, in the case where the
  693.       --  two types have unequal sizes, it is impossible for the result of
  694.       --  a remainder operation to be larger than the smaller of the two
  695.       --  types, so we can put a conversion round the result to keep the
  696.       --  evolving operation size as small as possible.
  697.  
  698.       if Esize (Left_Type) >= Esize (Right_Type) then
  699.          Rnode := Build_Conversion (N, Right_Type, Rnode);
  700.       elsif Esize (Right_Type) >= Esize (Left_Type) then
  701.          Rnode := Build_Conversion (N, Left_Type, Rnode);
  702.       end if;
  703.  
  704.       return Rnode;
  705.    end Build_Rem;
  706.  
  707.    -------------------------
  708.    -- Build_Scaled_Divide --
  709.    -------------------------
  710.  
  711.    function Build_Scaled_Divide
  712.      (N       : Node_Id;
  713.       X, Y, Z : Node_Id)
  714.       return    Node_Id
  715.    is
  716.       X_Size : constant Int := UI_To_Int (Esize (Etype (X)));
  717.       Y_Size : constant Int := UI_To_Int (Esize (Etype (Y)));
  718.       Expr   : Node_Id;
  719.  
  720.    begin
  721.       --  If numerator fits in 64 bits, we can build the operations directly
  722.       --  without causing any intermediate overflow, so that's what we do!
  723.  
  724.       if Int'Max (X_Size, Y_Size) <= 32 then
  725.          return
  726.            Build_Divide (N, Build_Multiply (N, X, Y), Z);
  727.  
  728.       --  Otherwise we use the runtime routine
  729.  
  730.       --    [Qnn : Integer_64,
  731.       --     Rnn : Integer_64;
  732.       --     Scaled_Divide (X, Y, Z, Qnn, Rnn, Round);
  733.       --     Qnn]
  734.  
  735.       else
  736.          declare
  737.             Loc  : constant Source_Ptr := Sloc (N);
  738.             Qnn  : Entity_Id;
  739.             Rnn  : Entity_Id;
  740.             Code : List_Id;
  741.  
  742.          begin
  743.             Build_Scaled_Divide_Code (N, X, Y, Z, Qnn, Rnn, Code);
  744.             Expr :=
  745.               Make_Expression_Actions (Loc,
  746.                 Actions    => Code,
  747.                 Expression => New_Occurrence_Of (Qnn, Loc));
  748.  
  749.             --  Set type of result in case used elsewhere (see note at start)
  750.  
  751.             Set_Etype (Expr, Etype (Qnn));
  752.             return Expr;
  753.          end;
  754.       end if;
  755.    end Build_Scaled_Divide;
  756.  
  757.    ------------------------------
  758.    -- Build_Scaled_Divide_Code --
  759.    ------------------------------
  760.  
  761.    --  If the numerator can be computed in 64-bits, we build
  762.  
  763.    --    [Nnn : constant typ := typ (X) * typ (Y);
  764.    --     Dnn : constant typ := typ (Z)
  765.    --     Qnn : constant typ := Nnn / Dnn;
  766.    --     Rnn : constant typ := Nnn / Dnn;
  767.  
  768.    --  If the numerator cannot be computed in 64 bits, we build
  769.  
  770.    --    [Qnn : Interfaces.Integer_64;
  771.    --     Rnn : Interfaces.Integer_64;
  772.    --     Scaled_Divide (X, Y, Z, Qnn, Rnn, Round);]
  773.  
  774.    procedure Build_Scaled_Divide_Code
  775.      (N        : Node_Id;
  776.       X, Y, Z  : Node_Id;
  777.       Qnn, Rnn : out Entity_Id;
  778.       Code     : out List_Id)
  779.    is
  780.       Loc    : constant Source_Ptr := Sloc (N);
  781.  
  782.       X_Size : constant Int := UI_To_Int (Esize (Etype (X)));
  783.       Y_Size : constant Int := UI_To_Int (Esize (Etype (Y)));
  784.       Z_Size : constant Int := UI_To_Int (Esize (Etype (Z)));
  785.  
  786.       QR_Siz : Int;
  787.       QR_Typ : Entity_Id;
  788.  
  789.       Nnn : Entity_Id;
  790.       Dnn : Entity_Id;
  791.  
  792.       Quo : Node_Id;
  793.       Rnd : Entity_Id;
  794.  
  795.    begin
  796.       --  Find type that will allow computation of numerator
  797.  
  798.       QR_Siz := Int'Max (X_Size, 2 * Int'Max (Y_Size, Z_Size));
  799.  
  800.       if QR_Siz <= 16 then
  801.          QR_Typ := Standard_Integer_16;
  802.       elsif QR_Siz <= 32 then
  803.          QR_Typ := Standard_Integer_32;
  804.       elsif QR_Siz <= 64 then
  805.          QR_Typ := Standard_Integer_64;
  806.  
  807.       --  For more than 64, bits, we use the 64-bit integer defined in
  808.       --  Interfaces, so that it can be handled by the runtime routine
  809.  
  810.       else
  811.          QR_Typ := RTE (RE_Integer_64);
  812.       end if;
  813.  
  814.       --  Define quotient and remainder, and set their Etypes, so
  815.       --  that they can be picked up by Build_xxx routines.
  816.  
  817.       Qnn := Make_Defining_Identifier (Loc, New_Internal_Name ('S'));
  818.       Rnn := Make_Defining_Identifier (Loc, New_Internal_Name ('R'));
  819.  
  820.       Set_Etype (Qnn, QR_Typ);
  821.       Set_Etype (Rnn, QR_Typ);
  822.  
  823.       --  Case that we can compute the numerator in 64 bits
  824.  
  825.       if QR_Siz <= 64 then
  826.          Nnn := Make_Defining_Identifier (Loc, New_Internal_Name  ('N'));
  827.          Dnn := Make_Defining_Identifier (Loc, New_Internal_Name  ('D'));
  828.  
  829.          --  Set Etypes, so that they can be picked up by New_Occurrence_Of
  830.  
  831.          Set_Etype (Nnn, QR_Typ);
  832.          Set_Etype (Dnn, QR_Typ);
  833.  
  834.          Code := New_List (
  835.            Make_Object_Declaration (Loc,
  836.              Defining_Identifier => Nnn,
  837.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc),
  838.              Constant_Present    => True,
  839.              Expression =>
  840.                Build_Multiply (N,
  841.                  Build_Conversion (N, QR_Typ, X),
  842.                  Build_Conversion (N, QR_Typ, Y))),
  843.  
  844.            Make_Object_Declaration (Loc,
  845.              Defining_Identifier => Dnn,
  846.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc),
  847.              Constant_Present    => True,
  848.              Expression => Build_Conversion (N, QR_Typ, Z)));
  849.  
  850.          Quo :=
  851.            Build_Divide (N,
  852.              New_Occurrence_Of (Nnn, Loc),
  853.              New_Occurrence_Of (Dnn, Loc));
  854.  
  855.          Append_To (Code,
  856.            Make_Object_Declaration (Loc,
  857.              Defining_Identifier => Qnn,
  858.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc),
  859.              Constant_Present    => True,
  860.              Expression          => Quo));
  861.  
  862.          Append_To (Code,
  863.            Make_Object_Declaration (Loc,
  864.              Defining_Identifier => Rnn,
  865.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc),
  866.              Constant_Present    => True,
  867.              Expression =>
  868.                Build_Rem (N,
  869.                  New_Occurrence_Of (Nnn, Loc),
  870.                  New_Occurrence_Of (Dnn, Loc))));
  871.  
  872.       --  Case where numerator does not fit in 64 bits, so we have to
  873.       --  call the runtime routine to compute the quotient and remainder
  874.  
  875.       else
  876.          if Rounded_Result_Set (N) then
  877.             Rnd := Standard_True;
  878.          else
  879.             Rnd := Standard_False;
  880.          end if;
  881.  
  882.          Code := New_List (
  883.            Make_Object_Declaration (Loc,
  884.              Defining_Identifier => Qnn,
  885.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc)),
  886.  
  887.            Make_Object_Declaration (Loc,
  888.              Defining_Identifier => Rnn,
  889.              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc)),
  890.  
  891.            Make_Procedure_Call_Statement (Loc,
  892.              Name => New_Occurrence_Of (RTE (RE_Scaled_Divide), Loc),
  893.              Parameter_Associations => New_List (
  894.                Build_Conversion (N, QR_Typ, X),
  895.                Build_Conversion (N, QR_Typ, Y),
  896.                Build_Conversion (N, QR_Typ, Z),
  897.                New_Occurrence_Of (Qnn, Loc),
  898.                New_Occurrence_Of (Rnn, Loc),
  899.                New_Occurrence_Of (Rnd, Loc))));
  900.       end if;
  901.  
  902.       --  Set type of result, for use in caller.
  903.  
  904.       Set_Etype (Qnn, QR_Typ);
  905.    end Build_Scaled_Divide_Code;
  906.  
  907.    ---------------------------
  908.    -- Do_Divide_Fixed_Fixed --
  909.    ---------------------------
  910.  
  911.    --  We have:
  912.  
  913.    --    (Result_Value * Result_Small) =
  914.    --        (Left_Value * Left_Small) / (Right_Value * Right_Small)
  915.  
  916.    --    Result_Value = (Left_Value / Right_Value) *
  917.    --                   (Left_Small / (Right_Small * Result_Small));
  918.  
  919.    --  we can do the operation in integer arithmetic if this fraction is an
  920.    --  integer or the reciprocal of an integer, as detailed in (RM G.2.3(21)).
  921.    --  Otherwise the result is in the close result set and our approach is to
  922.    --  use floating-point to compute this close result.
  923.  
  924.    procedure Do_Divide_Fixed_Fixed (N : Node_Id) is
  925.       Left        : constant Node_Id   := Left_Opnd (N);
  926.       Right       : constant Node_Id   := Right_Opnd (N);
  927.       Left_Type   : constant Entity_Id := Etype (Left);
  928.       Right_Type  : constant Entity_Id := Etype (Right);
  929.       Result_Type : constant Entity_Id := Etype (N);
  930.       Right_Small : constant Ureal     := Small_Value (Right_Type);
  931.       Left_Small  : constant Ureal     := Small_Value (Left_Type);
  932.  
  933.       Result_Small : Ureal;
  934.       Frac         : Ureal;
  935.       Frac_Num     : Uint;
  936.       Frac_Den     : Uint;
  937.       Lit_Int      : Node_Id;
  938.  
  939.    begin
  940.       --  Get result small. If the result is an integer, treat it as though
  941.       --  it had a small of 1.0, all other processing is identical.
  942.  
  943.       if Is_Integer_Type (Result_Type) then
  944.          Result_Small := Ureal_1;
  945.       else
  946.          Result_Small := Small_Value (Result_Type);
  947.       end if;
  948.  
  949.       --  Get small ratio
  950.  
  951.       Frac     := Left_Small / (Right_Small * Result_Small);
  952.       Frac_Num := Norm_Num (Frac);
  953.       Frac_Den := Norm_Den (Frac);
  954.  
  955.       --  If the fraction is an integer, then we get the result by multiplying
  956.       --  the left operand by the integer, and then dividing by the right
  957.       --  operand (the order is important, if we did the divide first, we
  958.       --  would lose precision).
  959.  
  960.       if Frac_Den = 1 then
  961.          Lit_Int := Integer_Literal (N, Frac_Num);
  962.  
  963.          if Present (Lit_Int) then
  964.             Set_Result (N, Build_Scaled_Divide (N, Left, Lit_Int, Right));
  965.             return;
  966.          end if;
  967.  
  968.       --  If the fraction is the reciprocal of an integer, then we get the
  969.       --  result by first multiplying the divisor by the integer, and then
  970.       --  doing the division with the adjusted divisor.
  971.  
  972.       --  Note: this is much better than doing two divisions: multiplications
  973.       --  are much faster than divisions (and certainly faster than rounded
  974.       --  divisions), and we don't get inaccuracies from double rounding.
  975.  
  976.       elsif Frac_Num = 1 then
  977.          Lit_Int := Integer_Literal (N, Frac_Den);
  978.  
  979.          if Present (Lit_Int) then
  980.             Set_Result (N, Build_Double_Divide (N, Left, Right, Lit_Int));
  981.             return;
  982.          end if;
  983.       end if;
  984.  
  985.       --  If we fall through, we use floating-point to compute the result
  986.  
  987.       Set_Result (N,
  988.         Build_Multiply (N,
  989.           Build_Divide (N, Fpt_Value (Left), Fpt_Value (Right)),
  990.           Real_Literal (N, Frac)));
  991.  
  992.    end Do_Divide_Fixed_Fixed;
  993.  
  994.    -------------------------------
  995.    -- Do_Divide_Fixed_Universal --
  996.    -------------------------------
  997.  
  998.    --  We have:
  999.  
  1000.    --    (Result_Value * Result_Small) = (Left_Value * Left_Small) / Lit_Value;
  1001.    --    Result_Value = Left_Value * Left_Small /(Lit_Value * Result_Small);
  1002.  
  1003.    --  The result is required to be in the perfect result set if the literal
  1004.    --  can be factored so that the resulting small ratio is an integer or the
  1005.    --  reciprocal of an integer (RM G.2.3(21-22)). We now give a detailed
  1006.    --  analysis of these RM requirements:
  1007.  
  1008.    --  We must factor the literal, finding an integer K:
  1009.  
  1010.    --     Lit_Value = K * Right_Small
  1011.    --     Right_Small = Lit_Value / K
  1012.  
  1013.    --  such that the small ratio:
  1014.  
  1015.    --              Left_Small
  1016.    --     ------------------------------
  1017.    --     (Lit_Value / K) * Result_Small
  1018.  
  1019.    --            Left_Small
  1020.    --  =  ------------------------  *  K
  1021.    --     Lit_Value * Result_Small
  1022.  
  1023.    --  is an integer or the reciprocal of an integer, and for
  1024.    --  implementation efficiency we need the smallest such K.
  1025.  
  1026.    --  First we reduce the left fraction to lowest terms.
  1027.  
  1028.    --    If numerator = 1, then for K = 1, the small ratio is the reciprocal
  1029.    --    of an integer, and this is clearly the minimum K case, so set K = 1,
  1030.    --    Right_Small = Lit_Value.
  1031.  
  1032.    --    If numerator > 1, then set K to the denominator of the fraction so
  1033.    --    that the resulting small ratio is an integer (the numerator value).
  1034.  
  1035.    procedure Do_Divide_Fixed_Universal (N : Node_Id) is
  1036.       Left        : constant Node_Id   := Left_Opnd (N);
  1037.       Right       : constant Node_Id   := Right_Opnd (N);
  1038.       Left_Type   : constant Entity_Id := Etype (Left);
  1039.       Result_Type : constant Entity_Id := Etype (N);
  1040.       Left_Small  : constant Ureal     := Small_Value (Left_Type);
  1041.       Lit_Value   : constant Ureal     := Realval (Right);
  1042.  
  1043.       Result_Small : Ureal;
  1044.       Frac         : Ureal;
  1045.       Frac_Num     : Uint;
  1046.       Frac_Den     : Uint;
  1047.       Lit_K        : Node_Id;
  1048.       Lit_Int      : Node_Id;
  1049.  
  1050.    begin
  1051.       --  Get result small. If the result is an integer, treat it as though
  1052.       --  it had a small of 1.0, all other processing is identical.
  1053.  
  1054.       if Is_Integer_Type (Result_Type) then
  1055.          Result_Small := Ureal_1;
  1056.       else
  1057.          Result_Small := Small_Value (Result_Type);
  1058.       end if;
  1059.  
  1060.       --  Determine if literal can be rewritten successfully
  1061.  
  1062.       Frac     := Left_Small / (Lit_Value * Result_Small);
  1063.       Frac_Num := Norm_Num (Frac);
  1064.       Frac_Den := Norm_Den (Frac);
  1065.  
  1066.       --  Case where fraction is the reciprocal of an integer (K = 1, integer
  1067.       --  = denominator). If this integer is not too large, this is the case
  1068.       --  where the result can be obtained by dividing by this integer value.
  1069.  
  1070.       if Frac_Num = 1 then
  1071.          Lit_Int := Integer_Literal (N, Frac_Den);
  1072.  
  1073.          if Present (Lit_Int) then
  1074.             Set_Result (N, Build_Divide (N, Left, Lit_Int));
  1075.             return;
  1076.          end if;
  1077.  
  1078.       --  Case where we choose K to make fraction an integer (K = denominator
  1079.       --  of fraction, integer = numerator of fraction). If both K and the
  1080.       --  numerator are small enough, this is the case where the result can
  1081.       --  be obtained by first multiplying by the integer value and then
  1082.       --  dividing by K (the order is important, if we divided first, we
  1083.       --  would lose precision).
  1084.  
  1085.       else
  1086.          Lit_Int := Integer_Literal (N, Frac_Num);
  1087.          Lit_K   := Integer_Literal (N, Frac_Den);
  1088.  
  1089.          if Present (Lit_Int) and then Present (Lit_K) then
  1090.             Set_Result (N, Build_Scaled_Divide (N, Left, Lit_Int, Lit_K));
  1091.             return;
  1092.          end if;
  1093.       end if;
  1094.  
  1095.       --  Fall through if the literal cannot be successfully rewritten, or if
  1096.       --  the small ratio is out of range of integer arithmetic. In the former
  1097.       --  case it is fine to use floating-point to get the close result set,
  1098.       --  and in the latter case, it means that the result is zero or raises
  1099.       --  constraint error, and we can do that accurately in floating-point.
  1100.  
  1101.       --  If we end up using floating-point, then we take the right integer
  1102.       --  to be one, and its small to be the value of the original right real
  1103.       --  literal. That way, we need only one floating-point multiplication.
  1104.  
  1105.       Set_Result (N,
  1106.         Build_Multiply (N, Fpt_Value (Left), Real_Literal (N, Frac)));
  1107.  
  1108.    end Do_Divide_Fixed_Universal;
  1109.  
  1110.    -------------------------------
  1111.    -- Do_Divide_Universal_Fixed --
  1112.    -------------------------------
  1113.  
  1114.    --  We have:
  1115.  
  1116.    --    (Result_Value * Result_Small) =
  1117.    --          Lit_Value / (Right_Value * Right_Small)
  1118.    --    Result_Value =
  1119.    --          (Lit_Value / (Right_Small * Result_Small)) / Right_Value
  1120.  
  1121.    --  The result is required to be in the perfect result set if the literal
  1122.    --  can be factored so that the resulting small ratio is an integer or the
  1123.    --  reciprocal of an integer (RM G.2.3(21-22)). We now give a detailed
  1124.    --  analysis of these RM requirements:
  1125.  
  1126.    --  We must factor the literal, finding an integer K:
  1127.  
  1128.    --     Lit_Value = K * Left_Small
  1129.    --     Left_Small = Lit_Value / K
  1130.  
  1131.    --  such that the small ratio:
  1132.  
  1133.    --           (Lit_Value / K)
  1134.    --     --------------------------
  1135.    --     Right_Small * Result_Small
  1136.  
  1137.    --              Lit_Value             1
  1138.    --  =  --------------------------  *  -
  1139.    --     Right_Small * Result_Small     K
  1140.  
  1141.    --  is an integer or the reciprocal of an integer, and for
  1142.    --  implementation efficiency we need the smallest such K.
  1143.  
  1144.    --  First we reduce the left fraction to lowest terms.
  1145.  
  1146.    --    If denominator = 1, then for K = 1, the small ratio is an integer
  1147.    --    (the numerator) and this is clearly the minimum K case, so set K = 1,
  1148.    --    and Left_Small = Lit_Value.
  1149.  
  1150.    --    If denominator > 1, then set K to the numerator of the fraction so
  1151.    --    that the resulting small ratio is the reciprocal of an integer (the
  1152.    --    numerator value).
  1153.  
  1154.    procedure Do_Divide_Universal_Fixed (N : Node_Id) is
  1155.       Left        : constant Node_Id   := Left_Opnd (N);
  1156.       Right       : constant Node_Id   := Right_Opnd (N);
  1157.       Right_Type  : constant Entity_Id := Etype (Right);
  1158.       Result_Type : constant Entity_Id := Etype (N);
  1159.       Right_Small : constant Ureal     := Small_Value (Right_Type);
  1160.       Lit_Value   : constant Ureal     := Realval (Left);
  1161.  
  1162.       Result_Small : Ureal;
  1163.       Frac         : Ureal;
  1164.       Frac_Num     : Uint;
  1165.       Frac_Den     : Uint;
  1166.       Lit_K        : Node_Id;
  1167.       Lit_Int      : Node_Id;
  1168.  
  1169.    begin
  1170.       --  Get result small. If the result is an integer, treat it as though
  1171.       --  it had a small of 1.0, all other processing is identical.
  1172.  
  1173.       if Is_Integer_Type (Result_Type) then
  1174.          Result_Small := Ureal_1;
  1175.       else
  1176.          Result_Small := Small_Value (Result_Type);
  1177.       end if;
  1178.  
  1179.       --  Determine if literal can be rewritten successfully
  1180.  
  1181.       Frac     := Lit_Value / (Right_Small * Result_Small);
  1182.       Frac_Num := Norm_Num (Frac);
  1183.       Frac_Den := Norm_Den (Frac);
  1184.  
  1185.       --  Case where fraction is an integer (K = 1, integer = numerator). If
  1186.       --  this integer is not too large, this is the case where the result
  1187.       --  can be obtained by dividing this integer by the right operand.
  1188.  
  1189.       if Frac_Den = 1 then
  1190.          Lit_Int := Integer_Literal (N, Frac_Num);
  1191.  
  1192.          if Present (Lit_Int) then
  1193.             Set_Result (N, Build_Divide (N, Lit_Int, Right));
  1194.             return;
  1195.          end if;
  1196.  
  1197.       --  Case where we choose K to make the fraction the reciprocal of an
  1198.       --  integer (K = numerator of fraction, integer = numerator of fraction).
  1199.       --  If both K and the integer are small enough, this is the case where
  1200.       --  the result can be obtained by multiplying the right operand by K
  1201.       --  and then dividing by the integer value. The order of the operations
  1202.       --  is important (if we divided first, we would lose precision).
  1203.  
  1204.       else
  1205.          Lit_Int := Integer_Literal (N, Frac_Den);
  1206.          Lit_K   := Integer_Literal (N, Frac_Num);
  1207.  
  1208.          if Present (Lit_Int) and then Present (Lit_K) then
  1209.             Set_Result (N, Build_Scaled_Divide (N, Right, Lit_K, Lit_Int));
  1210.             return;
  1211.          end if;
  1212.       end if;
  1213.  
  1214.       --  Fall through if the literal cannot be successfully rewritten, or if
  1215.       --  the small ratio is out of range of integer arithmetic. In the former
  1216.       --  case it is fine to use floating-point to get the close result set,
  1217.       --  and in the latter case, it means that the result is zero or raises
  1218.       --  constraint error, and we can do that accurately in floating-point.
  1219.  
  1220.       --  If we end up using floating-point, then we take the right integer
  1221.       --  to be one, and its small to be the value of the original right real
  1222.       --  literal. That way, we need only one floating-point division.
  1223.  
  1224.       Set_Result (N,
  1225.         Build_Divide (N, Real_Literal (N, Frac), Fpt_Value (Right)));
  1226.  
  1227.    end Do_Divide_Universal_Fixed;
  1228.  
  1229.    -----------------------------
  1230.    -- Do_Multiply_Fixed_Fixed --
  1231.    -----------------------------
  1232.  
  1233.    --  We have:
  1234.  
  1235.    --    (Result_Value * Result_Small) =
  1236.    --        (Left_Value * Left_Small) * (Right_Value * Right_Small)
  1237.  
  1238.    --    Result_Value = (Left_Value * Right_Value) *
  1239.    --                   (Left_Small * Right_Small) / Result_Small;
  1240.  
  1241.    --  we can do the operation in integer arithmetic if this fraction is an
  1242.    --  integer or the reciprocal of an integer, as detailed in (RM G.2.3(21)).
  1243.    --  Otherwise the result is in the close result set and our approach is to
  1244.    --  use floating-point to compute this close result.
  1245.  
  1246.    procedure Do_Multiply_Fixed_Fixed (N : Node_Id) is
  1247.       Left  : constant Node_Id := Left_Opnd (N);
  1248.       Right : constant Node_Id := Right_Opnd (N);
  1249.  
  1250.       Left_Type   : constant Entity_Id := Etype (Left);
  1251.       Right_Type  : constant Entity_Id := Etype (Right);
  1252.       Result_Type : constant Entity_Id := Etype (N);
  1253.       Right_Small : constant Ureal     := Small_Value (Right_Type);
  1254.       Left_Small  : constant Ureal     := Small_Value (Left_Type);
  1255.  
  1256.       Result_Small : Ureal;
  1257.       Frac         : Ureal;
  1258.       Frac_Num     : Uint;
  1259.       Frac_Den     : Uint;
  1260.       Lit_Int      : Node_Id;
  1261.  
  1262.    begin
  1263.       --  Get result small. If the result is an integer, treat it as though
  1264.       --  it had a small of 1.0, all other processing is identical.
  1265.  
  1266.       if Is_Integer_Type (Result_Type) then
  1267.          Result_Small := Ureal_1;
  1268.       else
  1269.          Result_Small := Small_Value (Result_Type);
  1270.       end if;
  1271.  
  1272.       --  Get small ratio
  1273.  
  1274.       Frac     := (Left_Small * Right_Small) / Result_Small;
  1275.       Frac_Num := Norm_Num (Frac);
  1276.       Frac_Den := Norm_Den (Frac);
  1277.  
  1278.       --  If the fraction is an integer, then we get the result by multiplying
  1279.       --  the operands, and then multiplying the result by the integer value.
  1280.  
  1281.       if Frac_Den = 1 then
  1282.          Lit_Int := Integer_Literal (N, Frac_Num);
  1283.  
  1284.          if Present (Lit_Int) then
  1285.             Set_Result (N,
  1286.               Build_Multiply (N, Build_Multiply (N, Left, Right),
  1287.                 Lit_Int));
  1288.             return;
  1289.          end if;
  1290.  
  1291.       --  If the fraction is the reciprocal of an integer, then we get the
  1292.       --  result by multiplying the operands, and then dividing the result by
  1293.       --  the integer value. The order of the operations is important, if we
  1294.       --  divided first, we would lose precision.
  1295.  
  1296.       elsif Frac_Num = 1 then
  1297.          Lit_Int := Integer_Literal (N, Frac_Den);
  1298.  
  1299.          if Present (Lit_Int) then
  1300.             Set_Result (N, Build_Scaled_Divide (N, Left, Right, Lit_Int));
  1301.             return;
  1302.          end if;
  1303.       end if;
  1304.  
  1305.       --  If we fall through, we use floating-point to compute the result
  1306.  
  1307.       Set_Result (N,
  1308.         Build_Multiply (N,
  1309.           Build_Multiply (N, Fpt_Value (Left), Fpt_Value (Right)),
  1310.           Real_Literal (N, Frac)));
  1311.  
  1312.    end Do_Multiply_Fixed_Fixed;
  1313.  
  1314.    ---------------------------------
  1315.    -- Do_Multiply_Fixed_Universal --
  1316.    ---------------------------------
  1317.  
  1318.    --  We have:
  1319.  
  1320.    --    (Result_Value * Result_Small) = (Left_Value * Left_Small) * Lit_Value;
  1321.    --    Result_Value = Left_Value * (Left_Small * Lit_Value) / Result_Small;
  1322.  
  1323.    --  The result is required to be in the perfect result set if the literal
  1324.    --  can be factored so that the resulting small ratio is an integer or the
  1325.    --  reciprocal of an integer (RM G.2.3(21-22)). We now give a detailed
  1326.    --  analysis of these RM requirements:
  1327.  
  1328.    --  We must factor the literal, finding an integer K:
  1329.  
  1330.    --     Lit_Value = K * Right_Small
  1331.    --     Right_Small = Lit_Value / K
  1332.  
  1333.    --  such that the small ratio:
  1334.  
  1335.    --     Left_Small * (Lit_Value / K)
  1336.    --     ----------------------------
  1337.    --             Result_Small
  1338.  
  1339.    --     Left_Small * Lit_Value     1
  1340.    --  =  ----------------------  *  -
  1341.    --          Result_Small          K
  1342.  
  1343.    --  is an integer or the reciprocal of an integer, and for
  1344.    --  implementation efficiency we need the smallest such K.
  1345.  
  1346.    --  First we reduce the left fraction to lowest terms.
  1347.  
  1348.    --    If denominator = 1, then for K = 1, the small ratio is an
  1349.    --    integer, and this is clearly the minimum K case, so set
  1350.    --    K = 1, Right_Small = Lit_Value.
  1351.  
  1352.    --    If denominator > 1, then set K to the numerator of the
  1353.    --    fraction, so that the resulting small ratio is the
  1354.    --    reciprocal of the integer (the denominator value).
  1355.  
  1356.    procedure Do_Multiply_Fixed_Universal
  1357.      (N           : Node_Id;
  1358.       Left, Right : Node_Id)
  1359.    is
  1360.       Left_Type   : constant Entity_Id := Etype (Left);
  1361.       Right_Type  : constant Entity_Id := Etype (Right);
  1362.       Result_Type : constant Entity_Id := Etype (N);
  1363.       Left_Small  : constant Ureal     := Small_Value (Left_Type);
  1364.       Lit_Value   : constant Ureal     := Realval (Right);
  1365.  
  1366.       Result_Small : Ureal;
  1367.       Frac         : Ureal;
  1368.       Frac_Num     : Uint;
  1369.       Frac_Den     : Uint;
  1370.       Lit_K        : Node_Id;
  1371.       Lit_Int      : Node_Id;
  1372.  
  1373.    begin
  1374.       --  Get result small. If the result is an integer, treat it as though
  1375.       --  it had a small of 1.0, all other processing is identical.
  1376.  
  1377.       if Is_Integer_Type (Result_Type) then
  1378.          Result_Small := Ureal_1;
  1379.       else
  1380.          Result_Small := Small_Value (Result_Type);
  1381.       end if;
  1382.  
  1383.       --  Determine if literal can be rewritten successfully
  1384.  
  1385.       Frac     := (Left_Small * Lit_Value) / Result_Small;
  1386.       Frac_Num := Norm_Num (Frac);
  1387.       Frac_Den := Norm_Den (Frac);
  1388.  
  1389.       --  Case where fraction is an integer (K = 1, integer = numerator). If
  1390.       --  this integer is not too large, this is the case where the result can
  1391.       --  be obtained by multiplying by this integer value.
  1392.  
  1393.       if Frac_Den = 1 then
  1394.          Lit_Int := Integer_Literal (N, Frac_Num);
  1395.  
  1396.          if Present (Lit_Int) then
  1397.             Set_Result (N, Build_Multiply (N, Left, Lit_Int));
  1398.             return;
  1399.          end if;
  1400.  
  1401.       --  Case where we choose K to make fraction the reciprocal of an integer
  1402.       --  (K = numerator of fraction, integer = denominator of fraction). If
  1403.       --  both K and the denominator are small enough, this is the case where
  1404.       --  the result can be obtained by first multiplying by K, and then
  1405.       --  dividing by the integer value.
  1406.  
  1407.       else
  1408.          Lit_Int := Integer_Literal (N, Frac_Den);
  1409.          Lit_K   := Integer_Literal (N, Frac_Num);
  1410.  
  1411.          if Present (Lit_Int) and then Present (Lit_K) then
  1412.             Set_Result (N, Build_Scaled_Divide (N, Left, Lit_K, Lit_Int));
  1413.             return;
  1414.          end if;
  1415.       end if;
  1416.  
  1417.       --  Fall through if the literal cannot be successfully rewritten, or if
  1418.       --  the small ratio is out of range of integer arithmetic. In the former
  1419.       --  case it is fine to use floating-point to get the close result set,
  1420.       --  and in the latter case, it means that the result is zero or raises
  1421.       --  constraint error, and we can do that accurately in floating-point.
  1422.  
  1423.       --  If we end up using floating-point, then we take the right integer
  1424.       --  to be one, and its small to be the value of the original right real
  1425.       --  literal. That way, we need only one floating-point multiplication.
  1426.  
  1427.       Set_Result (N,
  1428.         Build_Multiply (N, Fpt_Value (Left), Real_Literal (N, Frac)));
  1429.  
  1430.    end Do_Multiply_Fixed_Universal;
  1431.  
  1432.    -----------------------------------
  1433.    -- Expand_Convert_Fixed_To_Fixed --
  1434.    -----------------------------------
  1435.  
  1436.    --  We have:
  1437.  
  1438.    --    Result_Value * Result_Small = Source_Value * Source_Small
  1439.    --    Result_Value = Source_Value * (Source_Small / Result_Small)
  1440.  
  1441.    --  If the small ratio (Source_Small / Result_Small) is a sufficiently small
  1442.    --  integer, then the perfect result set is obtained by a single integer
  1443.    --  multiplication.
  1444.  
  1445.    --  If the small ratio is the reciprocal of a sufficiently small integer,
  1446.    --  then the perfect result set is obtained by a single integer division.
  1447.  
  1448.    --  In other cases, we obtain the close result set by calculating the
  1449.    --  result in floating-point.
  1450.  
  1451.    procedure Expand_Convert_Fixed_To_Fixed (N : Node_Id) is
  1452.       Expr        : constant Node_Id   := Expression (N);
  1453.       Result_Type : constant Entity_Id := Etype (N);
  1454.       Source_Type : constant Entity_Id := Etype (Expr);
  1455.       Small_Ratio : Ureal;
  1456.       Ratio_Num   : Uint;
  1457.       Ratio_Den   : Uint;
  1458.       Lit         : Node_Id;
  1459.  
  1460.    begin
  1461.       Small_Ratio := Small_Value (Source_Type) / Small_Value (Result_Type);
  1462.       Ratio_Num   := Norm_Num (Small_Ratio);
  1463.       Ratio_Den   := Norm_Den (Small_Ratio);
  1464.  
  1465.       if Ratio_Den = 1 then
  1466.  
  1467.          if Ratio_Num = 1 then
  1468.             Set_Result (N, Expr);
  1469.             return;
  1470.  
  1471.          else
  1472.             Lit := Integer_Literal (N, Ratio_Num);
  1473.  
  1474.             if Present (Lit) then
  1475.                Set_Result (N, Build_Multiply (N, Expr, Lit));
  1476.                return;
  1477.             end if;
  1478.          end if;
  1479.  
  1480.       elsif Ratio_Num = 1 then
  1481.          Lit := Integer_Literal (N, Ratio_Den);
  1482.  
  1483.          if Present (Lit) then
  1484.             Set_Result (N, Build_Divide (N, Expr, Lit));
  1485.             return;
  1486.          end if;
  1487.       end if;
  1488.  
  1489.       --  Fall through to use floating-point for the close result set case
  1490.       --  either as a result of the small ratio not being an integer or the
  1491.       --  reciprocal of an integer, or if the integer is out of range.
  1492.  
  1493.       Set_Result (N,
  1494.         Build_Multiply (N,
  1495.           Fpt_Value (Expr),
  1496.           Real_Literal (N, Small_Ratio)));
  1497.  
  1498.    end Expand_Convert_Fixed_To_Fixed;
  1499.  
  1500.    -----------------------------------
  1501.    -- Expand_Convert_Fixed_To_Float --
  1502.    -----------------------------------
  1503.  
  1504.    --  If the small of the fixed type is 1.0, then we simply convert the
  1505.    --  integer value directly to the target floating-point type, otherwise
  1506.    --  we first have to multiply by the small, in Long_Long_Float, and then
  1507.    --  convert the result to the target floating-point type.
  1508.  
  1509.    procedure Expand_Convert_Fixed_To_Float (N : Node_Id) is
  1510.       Loc         : constant Source_Ptr := Sloc (N);
  1511.       Expr        : constant Node_Id    := Expression (N);
  1512.       Result_Type : constant Entity_Id  := Etype (N);
  1513.       Source_Type : constant Entity_Id  := Etype (Expr);
  1514.       Small       : constant Ureal      := Small_Value (Source_Type);
  1515.  
  1516.    begin
  1517.       if Small = Ureal_1 then
  1518.          Set_Result (N, Expr);
  1519.  
  1520.       else
  1521.          Set_Result (N,
  1522.            Build_Multiply (N,
  1523.              Fpt_Value (Expr),
  1524.              Real_Literal (N, Small)));
  1525.       end if;
  1526.    end Expand_Convert_Fixed_To_Float;
  1527.  
  1528.    -------------------------------------
  1529.    -- Expand_Convert_Fixed_To_Integer --
  1530.    -------------------------------------
  1531.  
  1532.    --  We have:
  1533.  
  1534.    --    Result_Value = Source_Value * Source_Small
  1535.  
  1536.    --  If the small value is a sufficiently small integer, then the perfect
  1537.    --  result set is obtained by a single integer multiplication.
  1538.  
  1539.    --  If the small value is the reciprocal of a sufficiently small integer,
  1540.    --  then the perfect result set is obtained by a single integer division.
  1541.  
  1542.    --  In other cases, we obtain the close result set by calculating the
  1543.    --  result in floating-point.
  1544.  
  1545.    procedure Expand_Convert_Fixed_To_Integer (N : Node_Id) is
  1546.       Expr        : constant Node_Id   := Expression (N);
  1547.       Source_Type : constant Entity_Id := Etype (Expr);
  1548.       Small       : constant Ureal     := Small_Value (Source_Type);
  1549.       Small_Num   : constant Uint      := Norm_Num (Small);
  1550.       Small_Den   : constant Uint      := Norm_Den (Small);
  1551.       Lit         : Node_Id;
  1552.  
  1553.    begin
  1554.       if Small_Den = 1 then
  1555.          Lit := Integer_Literal (N, Small_Num);
  1556.  
  1557.          if Present (Lit) then
  1558.             Set_Result (N, Build_Multiply (N, Expr, Lit));
  1559.             return;
  1560.          end if;
  1561.  
  1562.       elsif Small_Num = 1 then
  1563.          Lit := Integer_Literal (N, Small_Den);
  1564.  
  1565.          if Present (Lit) then
  1566.             Set_Result (N, Build_Divide (N, Expr, Lit));
  1567.             return;
  1568.          end if;
  1569.       end if;
  1570.  
  1571.       --  Fall through to use floating-point for the close result set case
  1572.       --  either as a result of the small value not being an integer or the
  1573.       --  reciprocal of an integer, or if the integer is out of range.
  1574.  
  1575.       Set_Result (N,
  1576.         Build_Multiply (N,
  1577.           Fpt_Value (Expr),
  1578.           Real_Literal (N, Small)));
  1579.  
  1580.    end Expand_Convert_Fixed_To_Integer;
  1581.  
  1582.    -----------------------------------
  1583.    -- Expand_Convert_Float_To_Fixed --
  1584.    -----------------------------------
  1585.  
  1586.    --  We have
  1587.  
  1588.    --    Result_Value * Result_Small = Operand_Value
  1589.  
  1590.    --  so compute:
  1591.  
  1592.    --    Result_Value = Operand_Value * (1.0 / Result_Small)
  1593.  
  1594.    --  We do the small scaling in floating-point, and we do a multiplication
  1595.    --  rather than a division, since it is accurate enough for the perfect
  1596.    --  result cases, and faster.
  1597.  
  1598.    procedure Expand_Convert_Float_To_Fixed (N : Node_Id) is
  1599.       Expr        : constant Node_Id   := Expression (N);
  1600.       Result_Type : constant Entity_Id := Etype (N);
  1601.       Small       : constant Ureal     := Small_Value (Result_Type);
  1602.  
  1603.    begin
  1604.       --  Optimize small = 1, where we can avoid the multiply completely
  1605.  
  1606.       if Small = Ureal_1 then
  1607.          Set_Result (N, Expr);
  1608.  
  1609.       --  Normal case where multiply is required
  1610.  
  1611.       else
  1612.          Set_Result (N,
  1613.            Build_Multiply (N,
  1614.              Fpt_Value (Expr),
  1615.              Real_Literal (N, Ureal_1 / Small)));
  1616.       end if;
  1617.    end Expand_Convert_Float_To_Fixed;
  1618.  
  1619.    -------------------------------------
  1620.    -- Expand_Convert_Integer_To_Fixed --
  1621.    -------------------------------------
  1622.  
  1623.    --  We have
  1624.  
  1625.    --    Result_Value * Result_Small = Operand_Value
  1626.    --    Result_Value = Operand_Value / Result_Small
  1627.  
  1628.    --  If the small value is a sufficiently small integer, then the perfect
  1629.    --  result set is obtained by a single integer division.
  1630.  
  1631.    --  If the small value is the reciprocal of a sufficiently small integer,
  1632.    --  the perfect result set is obtained by a single integer multiplication.
  1633.  
  1634.    --  In other cases, we obtain the close result set by calculating the
  1635.    --  result in floating-point using a multiplication by the reciprocal
  1636.    --  of the Result_Small.
  1637.  
  1638.    procedure Expand_Convert_Integer_To_Fixed (N : Node_Id) is
  1639.       Expr        : constant Node_Id   := Expression (N);
  1640.       Result_Type : constant Entity_Id := Etype (N);
  1641.       Small       : constant Ureal     := Small_Value (Result_Type);
  1642.       Small_Num   : constant Uint      := Norm_Num (Small);
  1643.       Small_Den   : constant Uint      := Norm_Den (Small);
  1644.       Lit         : Node_Id;
  1645.  
  1646.    begin
  1647.       if Small_Den = 1 then
  1648.          Lit := Integer_Literal (N, Small_Num);
  1649.  
  1650.          if Present (Lit) then
  1651.             Set_Result (N, Build_Divide (N, Expr, Lit));
  1652.             return;
  1653.          end if;
  1654.  
  1655.       elsif Small_Num = 1 then
  1656.          Lit := Integer_Literal (N, Small_Den);
  1657.  
  1658.          if Present (Lit) then
  1659.             Set_Result (N, Build_Multiply (N, Expr, Lit));
  1660.             return;
  1661.          end if;
  1662.       end if;
  1663.  
  1664.       --  Fall through to use floating-point for the close result set case
  1665.       --  either as a result of the small value not being an integer or the
  1666.       --  reciprocal of an integer, or if the integer is out of range.
  1667.  
  1668.       Set_Result (N,
  1669.         Build_Multiply (N,
  1670.           Fpt_Value (Expr),
  1671.           Real_Literal (N, Ureal_1 / Small)));
  1672.  
  1673.    end Expand_Convert_Integer_To_Fixed;
  1674.  
  1675.    --------------------------------
  1676.    -- Expand_Decimal_Divide_Call --
  1677.    --------------------------------
  1678.  
  1679.    --  We have four operands
  1680.  
  1681.    --    Dividend
  1682.    --    Divisor
  1683.    --    Quotient
  1684.    --    Remainder
  1685.  
  1686.    --  All of which are decimal types, and which thus have associated
  1687.    --  decimal scales.
  1688.  
  1689.    --  Computing the quotient is a similar problem to that faced by the
  1690.    --  normal fixed-point division, except that it is simpler, because
  1691.    --  we always have compatible smalls.
  1692.  
  1693.    --    Quotient = (Dividend / Divisor) * 10**q
  1694.  
  1695.    --      where 10 ** q = Dividend'Small / (Divisor'Small * Quotient'Small)
  1696.    --      so q = Divisor'Scale + Quotient'Scale - Dividend'Scale
  1697.  
  1698.    --    For q >= 0, we compute
  1699.  
  1700.    --      Numerator   := Dividend * 10 ** q
  1701.    --      Denominator := Divisor
  1702.    --      Quotient    := Numerator / Denominator
  1703.  
  1704.    --    For q < 0, we compute
  1705.  
  1706.    --      Numerator   := Dividend
  1707.    --      Denominator := Divisor * 10 ** q
  1708.    --      Quotient    := Numerator / Denominator
  1709.  
  1710.    --  Both these divisions are done in truncated mode, and the remainder
  1711.    --  from these divisions is used to compute the result Remainder. This
  1712.    --  remainder has the effective scale of the numerator of the division,
  1713.  
  1714.    --    For q >= 0, the remainder scale is Dividend'Scale + q
  1715.    --    For q <  0, the remainder scale is Dividend'Scale
  1716.  
  1717.    --  The result Remainder is then computed by a normal truncating decimal
  1718.    --  conversion from this scale to the scale of the remainder, i.e. by a
  1719.    --  division or multiplication by the appropriate power of 10.
  1720.  
  1721.    procedure Expand_Decimal_Divide_Call (N : Node_Id) is
  1722.       Loc       : constant Source_Ptr := Sloc (N);
  1723.  
  1724.       Dividend  : Node_Id := First_Actual (N);
  1725.       Divisor   : Node_Id := Next_Actual (Dividend);
  1726.       Quotient  : Node_Id := Next_Actual (Divisor);
  1727.       Remainder : Node_Id := Next_Actual (Quotient);
  1728.  
  1729.       Dividend_Type   : constant Entity_Id := Etype (Dividend);
  1730.       Divisor_Type    : constant Entity_Id := Etype (Divisor);
  1731.       Quotient_Type   : constant Entity_Id := Etype (Quotient);
  1732.       Remainder_Type  : constant Entity_Id := Etype (Remainder);
  1733.  
  1734.       Dividend_Scale  : constant Uint := Scale_Value (Dividend_Type);
  1735.       Divisor_Scale   : constant Uint := Scale_Value (Divisor_Type);
  1736.       Quotient_Scale  : constant Uint := Scale_Value (Quotient_Type);
  1737.       Remainder_Scale : constant Uint := Scale_Value (Remainder_Type);
  1738.  
  1739.       Q                  : Uint;
  1740.       Numerator_Scale    : Uint;
  1741.       Stmts              : List_Id;
  1742.       Qnn                : Entity_Id;
  1743.       Rnn                : Entity_Id;
  1744.       Computed_Remainder : Node_Id;
  1745.       Adjusted_Remainder : Node_Id;
  1746.       Scale_Adjust       : Uint;
  1747.  
  1748.    begin
  1749.       --  Relocate the operands, since they are now list elements, and we
  1750.       --  need to reference them separately as operands in the expanded code.
  1751.  
  1752.       Dividend  := Relocate_Node (Dividend);
  1753.       Divisor   := Relocate_Node (Divisor);
  1754.       Quotient  := Relocate_Node (Quotient);
  1755.       Remainder := Relocate_Node (Remainder);
  1756.  
  1757.       --  Now compute Q, the adjustment scale
  1758.  
  1759.       Q := Divisor_Scale + Quotient_Scale - Dividend_Scale;
  1760.  
  1761.       --  If Q is non-negative then we need a scaled divide
  1762.  
  1763.       if Q >= 0 then
  1764.          Build_Scaled_Divide_Code
  1765.            (N,
  1766.             Dividend,
  1767.             Integer_Literal (N, Uint_10 ** Q),
  1768.             Divisor,
  1769.             Qnn, Rnn, Stmts);
  1770.  
  1771.          Numerator_Scale := Dividend_Scale + Q;
  1772.  
  1773.       --  If Q is negative, then we need a double divide
  1774.  
  1775.       else
  1776.          Build_Double_Divide_Code
  1777.            (N,
  1778.             Dividend,
  1779.             Divisor,
  1780.             Integer_Literal (N, Uint_10 ** (-Q)),
  1781.             Qnn, Rnn, Stmts);
  1782.  
  1783.          Numerator_Scale := Dividend_Scale;
  1784.       end if;
  1785.  
  1786.       --  Add statement to set quotient value
  1787.  
  1788.       --    Quotient := quotient-type!(Qnn);
  1789.  
  1790.       Append_To (Stmts,
  1791.         Make_Assignment_Statement (Loc,
  1792.           Name => Quotient,
  1793.           Expression =>
  1794.             Make_Unchecked_Type_Conversion (Loc,
  1795.               Subtype_Mark => New_Occurrence_Of (Quotient_Type, Loc),
  1796.               Expression =>
  1797.                 Build_Conversion (N, Quotient_Type,
  1798.                   New_Occurrence_Of (Qnn, Loc)))));
  1799.  
  1800.       --  Now we need to deal with computing and setting the remainder. The
  1801.       --  scale of the remainder is in Numerator_Scale, and the desired
  1802.       --  scale is the scale of the given Remainder argument. There are
  1803.       --  three cases:
  1804.  
  1805.       --    Numerator_Scale > Remainder_Scale
  1806.  
  1807.       --      in this case, there are extra digits in the computed remainder
  1808.       --      which must be eliminated by an extra division:
  1809.  
  1810.       --        computed-remainder := Numerator rem Denominator
  1811.       --        scale_adjust = Numerator_Scale - Remainder_Scale
  1812.       --        adjusted-remainder := computed-remainder / 10 ** scale_adjust
  1813.  
  1814.       --    Numerator_Scale = Remainder_Scale
  1815.  
  1816.       --      in this case, the we have the remainder we need
  1817.  
  1818.       --        computed-remainder := Numerator rem Denominator
  1819.       --        adjusted-remainder := computed-remainder
  1820.  
  1821.       --    Numerator_Scale < Remainder_Scale
  1822.  
  1823.       --      in this case, we have insufficient digits in the computed
  1824.       --      remainder, which must be eliminated by an extra multiply
  1825.  
  1826.       --        computed-remainder := Numerator rem Denominator
  1827.       --        scale_adjust = Remainder_Scale - Numerator_Scale
  1828.       --        adjusted-remainder := computed-remainder * 10 ** scale_adjust
  1829.  
  1830.       --  Finally we assign the adjusted-remainder to the result Remainder
  1831.       --  with conversions to get the proper fixed-point type representation.
  1832.  
  1833.       Computed_Remainder := New_Occurrence_Of (Rnn, Loc);
  1834.  
  1835.       if Numerator_Scale > Remainder_Scale then
  1836.          Scale_Adjust := Numerator_Scale - Remainder_Scale;
  1837.          Adjusted_Remainder :=
  1838.            Build_Divide
  1839.              (N, Computed_Remainder, Integer_Literal (N, 10 ** Scale_Adjust));
  1840.  
  1841.       elsif Numerator_Scale = Remainder_Scale then
  1842.          Adjusted_Remainder := Computed_Remainder;
  1843.  
  1844.       else -- Numerator_Scale < Remainder_Scale
  1845.          Scale_Adjust := Remainder_Scale - Numerator_Scale;
  1846.          Adjusted_Remainder :=
  1847.            Build_Multiply
  1848.              (N, Computed_Remainder, Integer_Literal (N, 10 ** Scale_Adjust));
  1849.       end if;
  1850.  
  1851.       --  Assignment of remainder result
  1852.  
  1853.       Append_To (Stmts,
  1854.         Make_Assignment_Statement (Loc,
  1855.           Name => Remainder,
  1856.           Expression =>
  1857.             Make_Unchecked_Type_Conversion (Loc,
  1858.               Subtype_Mark => New_Occurrence_Of (Remainder_Type, Loc),
  1859.               Expression   => Adjusted_Remainder)));
  1860.  
  1861.       --  Final step is to rewrite the call with a block containing the
  1862.       --  above sequence of constructed statements for the divide operation.
  1863.  
  1864.       Rewrite_Substitute_Tree (N,
  1865.         Make_Block_Statement (Loc,
  1866.           Handled_Statement_Sequence =>
  1867.             Make_Handled_Sequence_Of_Statements (Loc,
  1868.               Statements => Stmts)));
  1869.  
  1870.       Analyze (N);
  1871.  
  1872.    end Expand_Decimal_Divide_Call;
  1873.  
  1874.    -----------------------------------------------
  1875.    -- Expand_Divide_Fixed_By_Fixed_Giving_Fixed --
  1876.    -----------------------------------------------
  1877.  
  1878.    procedure Expand_Divide_Fixed_By_Fixed_Giving_Fixed (N : Node_Id) is
  1879.       Left  : constant Node_Id := Left_Opnd (N);
  1880.       Right : constant Node_Id := Right_Opnd (N);
  1881.  
  1882.    begin
  1883.       if Etype (Left) = Universal_Real then
  1884.          Do_Divide_Universal_Fixed (N);
  1885.  
  1886.       elsif Etype (Right) = Universal_Real then
  1887.          Do_Divide_Fixed_Universal (N);
  1888.  
  1889.       else
  1890.          Do_Divide_Fixed_Fixed (N);
  1891.       end if;
  1892.  
  1893.    end Expand_Divide_Fixed_By_Fixed_Giving_Fixed;
  1894.  
  1895.    -----------------------------------------------
  1896.    -- Expand_Divide_Fixed_By_Fixed_Giving_Float --
  1897.    -----------------------------------------------
  1898.  
  1899.    --  The division is done in long_long_float, and the result is multiplied
  1900.    --  by the small ratio, which is Small (Right) / Small (Left). Special
  1901.    --  treatment is required for universal operands, which represent their
  1902.    --  own value and do not require conversion.
  1903.  
  1904.    procedure Expand_Divide_Fixed_By_Fixed_Giving_Float (N : Node_Id) is
  1905.       Left  : constant Node_Id := Left_Opnd (N);
  1906.       Right : constant Node_Id := Right_Opnd (N);
  1907.  
  1908.       Left_Type   : constant Entity_Id := Etype (Left);
  1909.       Right_Type  : constant Entity_Id := Etype (Right);
  1910.       Result_Type : constant Entity_Id := Etype (N);
  1911.  
  1912.    begin
  1913.       --  Case of left operand is universal real, the result we want is:
  1914.  
  1915.       --    Left_Value / (Right_Value * Right_Small)
  1916.  
  1917.       --  so we compute this as:
  1918.  
  1919.       --    (Left_Value / Right_Small) / Right_Value
  1920.  
  1921.       if Left_Type = Universal_Real then
  1922.          Set_Result (N,
  1923.            Build_Divide (N,
  1924.              Real_Literal (N, Realval (Left) / Small_Value (Right_Type)),
  1925.              Fpt_Value (Right)));
  1926.  
  1927.       --  Case of right operand is universal real, the result we want is
  1928.  
  1929.       --    (Left_Value * Left_Small) / Right_Value
  1930.  
  1931.       --  so we compute this as:
  1932.  
  1933.       --    Left_Value * (Left_Small / Right_Value)
  1934.  
  1935.       --  Note we invert to a multiplication since usually floating-point
  1936.       --  multiplication is much faster than floating-point division.
  1937.  
  1938.       elsif Right_Type = Universal_Real then
  1939.          Set_Result (N,
  1940.            Build_Multiply (N,
  1941.              Fpt_Value (Left),
  1942.              Real_Literal (N, Small_Value (Left_Type) / Realval (Right))));
  1943.  
  1944.       --  Both operands are fixed, so the value we want is
  1945.  
  1946.       --    (Left_Value * Left_Small) / (Right_Value * Right_Small)
  1947.  
  1948.       --  which we compute as:
  1949.  
  1950.       --    (Left_Value / Right_Value) * (Left_Small / Right_Small)
  1951.  
  1952.       else
  1953.          Set_Result (N,
  1954.            Build_Multiply (N,
  1955.              Build_Divide (N, Fpt_Value (Left), Fpt_Value (Right)),
  1956.              Real_Literal (N,
  1957.                Small_Value (Left_Type) / Small_Value (Right_Type))));
  1958.       end if;
  1959.  
  1960.    end Expand_Divide_Fixed_By_Fixed_Giving_Float;
  1961.  
  1962.    -------------------------------------------------
  1963.    -- Expand_Divide_Fixed_By_Fixed_Giving_Integer --
  1964.    -------------------------------------------------
  1965.  
  1966.    procedure Expand_Divide_Fixed_By_Fixed_Giving_Integer (N : Node_Id) is
  1967.       Left  : constant Node_Id := Left_Opnd (N);
  1968.       Right : constant Node_Id := Right_Opnd (N);
  1969.  
  1970.    begin
  1971.       if Etype (Left) = Universal_Real then
  1972.          Do_Divide_Universal_Fixed (N);
  1973.  
  1974.       elsif Etype (Right) = Universal_Real then
  1975.          Do_Divide_Fixed_Universal (N);
  1976.  
  1977.       else
  1978.          Do_Divide_Fixed_Fixed (N);
  1979.       end if;
  1980.  
  1981.    end Expand_Divide_Fixed_By_Fixed_Giving_Integer;
  1982.  
  1983.    -------------------------------------------------
  1984.    -- Expand_Divide_Fixed_By_Integer_Giving_Fixed --
  1985.    -------------------------------------------------
  1986.  
  1987.    --  Since the operand and result fixed-point type is the same, this is
  1988.    --  a straight divide by the right operand, the small can be ignored.
  1989.  
  1990.    procedure Expand_Divide_Fixed_By_Integer_Giving_Fixed (N : Node_Id) is
  1991.       Left  : constant Node_Id := Left_Opnd (N);
  1992.       Right : constant Node_Id := Right_Opnd (N);
  1993.  
  1994.    begin
  1995.       Set_Result (N, Build_Divide (N, Left, Right));
  1996.    end Expand_Divide_Fixed_By_Integer_Giving_Fixed;
  1997.  
  1998.    -------------------------------------------------
  1999.    -- Expand_Multiply_Fixed_By_Fixed_Giving_Fixed --
  2000.    -------------------------------------------------
  2001.  
  2002.    procedure Expand_Multiply_Fixed_By_Fixed_Giving_Fixed (N : Node_Id) is
  2003.       Left  : constant Node_Id := Left_Opnd (N);
  2004.       Right : constant Node_Id := Right_Opnd (N);
  2005.  
  2006.    begin
  2007.       if Etype (Left) = Universal_Real then
  2008.          Do_Multiply_Fixed_Universal (N, Right, Left);
  2009.  
  2010.       elsif Etype (Right) = Universal_Real then
  2011.          Do_Multiply_Fixed_Universal (N, Left, Right);
  2012.  
  2013.       else
  2014.          Do_Multiply_Fixed_Fixed (N);
  2015.       end if;
  2016.  
  2017.    end Expand_Multiply_Fixed_By_Fixed_Giving_Fixed;
  2018.  
  2019.    -------------------------------------------------
  2020.    -- Expand_Multiply_Fixed_By_Fixed_Giving_Float --
  2021.    -------------------------------------------------
  2022.  
  2023.    --  The multiply is done in long_long_float, and the result is multiplied
  2024.    --  by the adjustment for the smalls which is Small (Right) * Small (Left).
  2025.    --  Special treatment is required for universal operands.
  2026.  
  2027.    procedure Expand_Multiply_Fixed_By_Fixed_Giving_Float (N : Node_Id) is
  2028.       Left  : constant Node_Id := Left_Opnd (N);
  2029.       Right : constant Node_Id := Right_Opnd (N);
  2030.  
  2031.       Left_Type   : constant Entity_Id := Etype (Left);
  2032.       Right_Type  : constant Entity_Id := Etype (Right);
  2033.       Result_Type : constant Entity_Id := Etype (N);
  2034.  
  2035.    begin
  2036.       --  Case of left operand is universal real, the result we want is
  2037.  
  2038.       --    Left_Value * (Right_Value * Right_Small)
  2039.  
  2040.       --  so we compute this as:
  2041.  
  2042.       --    (Left_Value * Right_Small) * Right_Value;
  2043.  
  2044.       if Left_Type = Universal_Real then
  2045.          Set_Result (N,
  2046.            Build_Multiply (N,
  2047.              Real_Literal (N, Realval (Left) * Small_Value (Right_Type)),
  2048.              Fpt_Value (Right)));
  2049.  
  2050.       --  Case of right operand is universal real, the result we want is
  2051.  
  2052.       --    (Left_Value * Left_Small) * Right_Value
  2053.  
  2054.       --  so we compute this as:
  2055.  
  2056.       --    Left_Value * (Left_Small * Right_Value)
  2057.  
  2058.       elsif Right_Type = Universal_Real then
  2059.          Set_Result (N,
  2060.            Build_Multiply (N,
  2061.              Fpt_Value (Left),
  2062.              Real_Literal (N, Small_Value (Left_Type) * Realval (Right))));
  2063.  
  2064.       --  Both operands are fixed, so the value we want is
  2065.  
  2066.       --    (Left_Value * Left_Small) * (Right_Value * Right_Small)
  2067.  
  2068.       --  which we compute as:
  2069.  
  2070.       --    (Left_Value * Right_Value) * (Right_Small * Left_Small)
  2071.  
  2072.       else
  2073.          Set_Result (N,
  2074.            Build_Multiply (N,
  2075.              Build_Multiply (N, Fpt_Value (Left), Fpt_Value (Right)),
  2076.              Real_Literal (N,
  2077.                Small_Value (Right_Type) * Small_Value (Left_Type))));
  2078.       end if;
  2079.  
  2080.    end Expand_Multiply_Fixed_By_Fixed_Giving_Float;
  2081.  
  2082.    ---------------------------------------------------
  2083.    -- Expand_Multiply_Fixed_By_Fixed_Giving_Integer --
  2084.    ---------------------------------------------------
  2085.  
  2086.    procedure Expand_Multiply_Fixed_By_Fixed_Giving_Integer (N : Node_Id) is
  2087.       Left  : constant Node_Id := Left_Opnd (N);
  2088.       Right : constant Node_Id := Right_Opnd (N);
  2089.  
  2090.    begin
  2091.       if Etype (Left) = Universal_Real then
  2092.          Do_Multiply_Fixed_Universal (N, Right, Left);
  2093.  
  2094.       elsif Etype (Right) = Universal_Real then
  2095.          Do_Multiply_Fixed_Universal (N, Left, Right);
  2096.  
  2097.       else
  2098.          Do_Multiply_Fixed_Fixed (N);
  2099.       end if;
  2100.  
  2101.    end Expand_Multiply_Fixed_By_Fixed_Giving_Integer;
  2102.  
  2103.    ---------------------------------------------------
  2104.    -- Expand_Multiply_Fixed_By_Integer_Giving_Fixed --
  2105.    ---------------------------------------------------
  2106.  
  2107.    --  Since the operand and result fixed-point type is the same, this is
  2108.    --  a straight multiply by the right operand, the small can be ignored.
  2109.  
  2110.    procedure Expand_Multiply_Fixed_By_Integer_Giving_Fixed (N : Node_Id) is
  2111.    begin
  2112.       Set_Result (N,
  2113.         Build_Multiply (N, Left_Opnd (N), Right_Opnd (N)));
  2114.    end Expand_Multiply_Fixed_By_Integer_Giving_Fixed;
  2115.  
  2116.    ---------------------------------------------------
  2117.    -- Expand_Multiply_Integer_By_Fixed_Giving_Fixed --
  2118.    ---------------------------------------------------
  2119.  
  2120.    --  Since the operand and result fixed-point type is the same, this is
  2121.    --  a straight multiply by the right operand, the small can be ignored.
  2122.  
  2123.    procedure Expand_Multiply_Integer_By_Fixed_Giving_Fixed (N : Node_Id) is
  2124.    begin
  2125.       Set_Result (N,
  2126.         Build_Multiply (N, Left_Opnd (N), Right_Opnd (N)));
  2127.    end Expand_Multiply_Integer_By_Fixed_Giving_Fixed;
  2128.  
  2129.    ---------------
  2130.    -- Fpt_Value --
  2131.    ---------------
  2132.  
  2133.    function Fpt_Value (N : Node_Id) return Node_Id is
  2134.       Typ   : constant Entity_Id  := Etype (N);
  2135.  
  2136.    begin
  2137.       if Is_Integer_Type (Typ)
  2138.         or else Is_Floating_Point_Type (Typ)
  2139.       then
  2140.          return
  2141.            Build_Conversion
  2142.              (N, Standard_Long_Long_Float, N);
  2143.  
  2144.       --  Fixed-point case, must get integer value first
  2145.  
  2146.       else
  2147.          return
  2148.            Build_Conversion (N, Standard_Long_Long_Float, N);
  2149.       end if;
  2150.  
  2151.    end Fpt_Value;
  2152.  
  2153.    ---------------------
  2154.    -- Integer_Literal --
  2155.    ---------------------
  2156.  
  2157.    function Integer_Literal (N : Node_Id; V : Uint) return Node_Id is
  2158.       T : Entity_Id;
  2159.       L : Node_Id;
  2160.  
  2161.    begin
  2162.       if V < Uint_2 ** 7 then
  2163.          T := Standard_Integer_8;
  2164.  
  2165.       elsif V < Uint_2 ** 15 then
  2166.          T := Standard_Integer_16;
  2167.  
  2168.       elsif V < Uint_2 ** 31 then
  2169.          T := Standard_Integer_32;
  2170.  
  2171.       elsif V < Uint_2 ** 63 then
  2172.          T := Standard_Integer_64;
  2173.  
  2174.       else
  2175.          return Empty;
  2176.       end if;
  2177.  
  2178.       L := Make_Integer_Literal (Sloc (N), V);
  2179.  
  2180.       --  Set type of result in case used elsewhere (see note at start)
  2181.  
  2182.       Set_Etype (L, T);
  2183.       Set_Is_Static_Expression (L);
  2184.  
  2185.       --  We really need to set Analyzed here because we may be creating a
  2186.       --  very strange beast, namely an integer literal typed as fixed-point
  2187.       --  and the analyzer won't like that. Probably we should allow the
  2188.       --  Treat_Fixed_As_Integer flag to appear on integer literal nodes
  2189.       --  and teach the analyzer how to handle them ???
  2190.  
  2191.       Set_Analyzed (L);
  2192.       return L;
  2193.  
  2194.    end Integer_Literal;
  2195.  
  2196.    ------------------
  2197.    -- Real_Literal --
  2198.    ------------------
  2199.  
  2200.    function Real_Literal (N : Node_Id; V : Ureal) return Node_Id is
  2201.       L : Node_Id;
  2202.  
  2203.    begin
  2204.       L := Make_Real_Literal (Sloc (N), V);
  2205.  
  2206.       --  Set type of result in case used elsewhere (see note at start)
  2207.  
  2208.       Set_Etype (L, Standard_Long_Long_Float);
  2209.       return L;
  2210.    end Real_Literal;
  2211.  
  2212.    ------------------------
  2213.    -- Rounded_Result_Set --
  2214.    ------------------------
  2215.  
  2216.    function Rounded_Result_Set (N : Node_Id) return Boolean is
  2217.       K : constant Node_Kind := Nkind (N);
  2218.  
  2219.    begin
  2220.       if (K = N_Type_Conversion or else
  2221.           K = N_Op_Divide       or else
  2222.           K = N_Op_Multiply)
  2223.         and then Rounded_Result (N)
  2224.       then
  2225.          return True;
  2226.       else
  2227.          return False;
  2228.       end if;
  2229.    end Rounded_Result_Set;
  2230.  
  2231.    ----------------
  2232.    -- Set_Result --
  2233.    ----------------
  2234.  
  2235.    procedure Set_Result (N : Node_Id; Expr : Node_Id) is
  2236.       Loc   : constant Source_Ptr := Sloc (N);
  2237.       Cnode : Node_Id;
  2238.  
  2239.       Expr_Type   : constant Entity_Id := Etype (Expr);
  2240.       Result_Type : constant Entity_Id := Etype (N);
  2241.       Itype       : Entity_Id;
  2242.  
  2243.    begin
  2244.       --  No conversion required if types match
  2245.  
  2246.       if Result_Type = Expr_Type then
  2247.          Cnode := Expr;
  2248.  
  2249.       --  Else perform required conversion
  2250.  
  2251.       else
  2252.          Cnode := Build_Conversion (N, Result_Type, Expr);
  2253.       end if;
  2254.  
  2255.       Rewrite_Substitute_Tree (N, Cnode);
  2256.       Analyze (N);
  2257.       Resolve (N, Result_Type);
  2258.  
  2259.    end Set_Result;
  2260.  
  2261. end Exp_Fixd;
  2262.