diff gcc/ada/doc/gnat_rm/implementation_of_specific_ada_features.rst @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 1830386684a0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/ada/doc/gnat_rm/implementation_of_specific_ada_features.rst	Fri Oct 27 22:46:09 2017 +0900
@@ -0,0 +1,703 @@
+.. _Implementation_of_Specific_Ada_Features:
+
+***************************************
+Implementation of Specific Ada Features
+***************************************
+
+This chapter describes the GNAT implementation of several Ada language
+facilities.
+
+.. _Machine_Code_Insertions:
+
+Machine Code Insertions
+=======================
+
+.. index:: Machine Code insertions
+
+Package ``Machine_Code`` provides machine code support as described
+in the Ada Reference Manual in two separate forms:
+
+*
+  Machine code statements, consisting of qualified expressions that
+  fit the requirements of RM section 13.8.
+*
+  An intrinsic callable procedure, providing an alternative mechanism of
+  including machine instructions in a subprogram.
+
+The two features are similar, and both are closely related to the mechanism
+provided by the asm instruction in the GNU C compiler.  Full understanding
+and use of the facilities in this package requires understanding the asm
+instruction, see the section on Extended Asm in
+:title:`Using_the_GNU_Compiler_Collection_(GCC)`.
+
+Calls to the function ``Asm`` and the procedure ``Asm`` have identical
+semantic restrictions and effects as described below.  Both are provided so
+that the procedure call can be used as a statement, and the function call
+can be used to form a code_statement.
+
+Consider this C ``asm`` instruction:
+
+::
+
+     asm ("fsinx %1 %0" : "=f" (result) : "f" (angle));
+
+
+The equivalent can be written for GNAT as:
+
+.. code-block:: ada
+
+  Asm ("fsinx %1 %0",
+       My_Float'Asm_Output ("=f", result),
+       My_Float'Asm_Input  ("f",  angle));
+
+
+The first argument to ``Asm`` is the assembler template, and is
+identical to what is used in GNU C.  This string must be a static
+expression.  The second argument is the output operand list.  It is
+either a single ``Asm_Output`` attribute reference, or a list of such
+references enclosed in parentheses (technically an array aggregate of
+such references).
+
+The ``Asm_Output`` attribute denotes a function that takes two
+parameters.  The first is a string, the second is the name of a variable
+of the type designated by the attribute prefix.  The first (string)
+argument is required to be a static expression and designates the
+constraint (see the section on Constraints in
+:title:`Using_the_GNU_Compiler_Collection_(GCC)`)
+for the parameter; e.g., what kind of register is required.  The second
+argument is the variable to be written or updated with the
+result.  The possible values for constraint are the same as those used in
+the RTL, and are dependent on the configuration file used to build the
+GCC back end.  If there are no output operands, then this argument may
+either be omitted, or explicitly given as ``No_Output_Operands``.
+No support is provided for GNU C's symbolic names for output parameters.
+
+The second argument of ``my_float'Asm_Output`` functions as
+though it were an ``out`` parameter, which is a little curious, but
+all names have the form of expressions, so there is no syntactic
+irregularity, even though normally functions would not be permitted
+``out`` parameters.  The third argument is the list of input
+operands.  It is either a single ``Asm_Input`` attribute reference, or
+a list of such references enclosed in parentheses (technically an array
+aggregate of such references).
+
+The ``Asm_Input`` attribute denotes a function that takes two
+parameters.  The first is a string, the second is an expression of the
+type designated by the prefix.  The first (string) argument is required
+to be a static expression, and is the constraint for the parameter,
+(e.g., what kind of register is required).  The second argument is the
+value to be used as the input argument.  The possible values for the
+constraint are the same as those used in the RTL, and are dependent on
+the configuration file used to built the GCC back end.
+No support is provided for GNU C's symbolic names for input parameters.
+
+If there are no input operands, this argument may either be omitted, or
+explicitly given as ``No_Input_Operands``.  The fourth argument, not
+present in the above example, is a list of register names, called the
+*clobber* argument.  This argument, if given, must be a static string
+expression, and is a space or comma separated list of names of registers
+that must be considered destroyed as a result of the ``Asm`` call.  If
+this argument is the null string (the default value), then the code
+generator assumes that no additional registers are destroyed.
+In addition to registers, the special clobbers ``memory`` and
+``cc`` as described in the GNU C docs are both supported.
+
+The fifth argument, not present in the above example, called the
+*volatile* argument, is by default ``False``.  It can be set to
+the literal value ``True`` to indicate to the code generator that all
+optimizations with respect to the instruction specified should be
+suppressed, and in particular an instruction that has outputs
+will still be generated, even if none of the outputs are
+used.  See :title:`Using_the_GNU_Compiler_Collection_(GCC)`
+for the full description.
+Generally it is strongly advisable to use Volatile for any ASM statement
+that is missing either input or output operands or to avoid unwanted
+optimizations. A warning is generated if this advice is not followed.
+
+No support is provided for GNU C's ``asm goto`` feature.
+
+The ``Asm`` subprograms may be used in two ways.  First the procedure
+forms can be used anywhere a procedure call would be valid, and
+correspond to what the RM calls 'intrinsic' routines.  Such calls can
+be used to intersperse machine instructions with other Ada statements.
+Second, the function forms, which return a dummy value of the limited
+private type ``Asm_Insn``, can be used in code statements, and indeed
+this is the only context where such calls are allowed.  Code statements
+appear as aggregates of the form:
+
+.. code-block:: ada
+
+  Asm_Insn'(Asm (...));
+  Asm_Insn'(Asm_Volatile (...));
+
+In accordance with RM rules, such code statements are allowed only
+within subprograms whose entire body consists of such statements.  It is
+not permissible to intermix such statements with other Ada statements.
+
+Typically the form using intrinsic procedure calls is more convenient
+and more flexible.  The code statement form is provided to meet the RM
+suggestion that such a facility should be made available.  The following
+is the exact syntax of the call to ``Asm``. As usual, if named notation
+is used, the arguments may be given in arbitrary order, following the
+normal rules for use of positional and named arguments:
+
+::
+
+  ASM_CALL ::= Asm (
+                   [Template =>] static_string_EXPRESSION
+                 [,[Outputs  =>] OUTPUT_OPERAND_LIST      ]
+                 [,[Inputs   =>] INPUT_OPERAND_LIST       ]
+                 [,[Clobber  =>] static_string_EXPRESSION ]
+                 [,[Volatile =>] static_boolean_EXPRESSION] )
+
+  OUTPUT_OPERAND_LIST ::=
+    [PREFIX.]No_Output_Operands
+  | OUTPUT_OPERAND_ATTRIBUTE
+  | (OUTPUT_OPERAND_ATTRIBUTE {,OUTPUT_OPERAND_ATTRIBUTE})
+
+  OUTPUT_OPERAND_ATTRIBUTE ::=
+    SUBTYPE_MARK'Asm_Output (static_string_EXPRESSION, NAME)
+
+  INPUT_OPERAND_LIST ::=
+    [PREFIX.]No_Input_Operands
+  | INPUT_OPERAND_ATTRIBUTE
+  | (INPUT_OPERAND_ATTRIBUTE {,INPUT_OPERAND_ATTRIBUTE})
+
+  INPUT_OPERAND_ATTRIBUTE ::=
+    SUBTYPE_MARK'Asm_Input (static_string_EXPRESSION, EXPRESSION)
+
+The identifiers ``No_Input_Operands`` and ``No_Output_Operands``
+are declared in the package ``Machine_Code`` and must be referenced
+according to normal visibility rules. In particular if there is no
+``use`` clause for this package, then appropriate package name
+qualification is required.
+
+.. _GNAT_Implementation_of_Tasking:
+
+GNAT Implementation of Tasking
+==============================
+
+This chapter outlines the basic GNAT approach to tasking (in particular,
+a multi-layered library for portability) and discusses issues related
+to compliance with the Real-Time Systems Annex.
+
+.. _Mapping_Ada_Tasks_onto_the_Underlying_Kernel_Threads:
+
+Mapping Ada Tasks onto the Underlying Kernel Threads
+----------------------------------------------------
+
+GNAT's run-time support comprises two layers:
+
+* GNARL (GNAT Run-time Layer)
+* GNULL (GNAT Low-level Library)
+
+In GNAT, Ada's tasking services rely on a platform and OS independent
+layer known as GNARL.  This code is responsible for implementing the
+correct semantics of Ada's task creation, rendezvous, protected
+operations etc.
+
+GNARL decomposes Ada's tasking semantics into simpler lower level
+operations such as create a thread, set the priority of a thread,
+yield, create a lock, lock/unlock, etc.  The spec for these low-level
+operations constitutes GNULLI, the GNULL Interface.  This interface is
+directly inspired from the POSIX real-time API.
+
+If the underlying executive or OS implements the POSIX standard
+faithfully, the GNULL Interface maps as is to the services offered by
+the underlying kernel.  Otherwise, some target dependent glue code maps
+the services offered by the underlying kernel to the semantics expected
+by GNARL.
+
+Whatever the underlying OS (VxWorks, UNIX, Windows, etc.) the
+key point is that each Ada task is mapped on a thread in the underlying
+kernel.  For example, in the case of VxWorks, one Ada task = one VxWorks task.
+
+In addition Ada task priorities map onto the underlying thread priorities.
+Mapping Ada tasks onto the underlying kernel threads has several advantages:
+
+*
+  The underlying scheduler is used to schedule the Ada tasks.  This
+  makes Ada tasks as efficient as kernel threads from a scheduling
+  standpoint.
+
+*
+  Interaction with code written in C containing threads is eased
+  since at the lowest level Ada tasks and C threads map onto the same
+  underlying kernel concept.
+
+*
+  When an Ada task is blocked during I/O the remaining Ada tasks are
+  able to proceed.
+
+*
+  On multiprocessor systems Ada tasks can execute in parallel.
+
+Some threads libraries offer a mechanism to fork a new process, with the
+child process duplicating the threads from the parent.
+GNAT does not
+support this functionality when the parent contains more than one task.
+
+.. index:: Forking a new process
+
+.. _Ensuring_Compliance_with_the_Real-Time_Annex:
+
+Ensuring Compliance with the Real-Time Annex
+--------------------------------------------
+
+.. index:: Real-Time Systems Annex compliance
+
+Although mapping Ada tasks onto
+the underlying threads has significant advantages, it does create some
+complications when it comes to respecting the scheduling semantics
+specified in the real-time annex (Annex D).
+
+For instance the Annex D requirement for the ``FIFO_Within_Priorities``
+scheduling policy states:
+
+  *When the active priority of a ready task that is not running
+  changes, or the setting of its base priority takes effect, the
+  task is removed from the ready queue for its old active priority
+  and is added at the tail of the ready queue for its new active
+  priority, except in the case where the active priority is lowered
+  due to the loss of inherited priority, in which case the task is
+  added at the head of the ready queue for its new active priority.*
+
+While most kernels do put tasks at the end of the priority queue when
+a task changes its priority, (which respects the main
+FIFO_Within_Priorities requirement), almost none keep a thread at the
+beginning of its priority queue when its priority drops from the loss
+of inherited priority.
+
+As a result most vendors have provided incomplete Annex D implementations.
+
+The GNAT run-time, has a nice cooperative solution to this problem
+which ensures that accurate FIFO_Within_Priorities semantics are
+respected.
+
+The principle is as follows.  When an Ada task T is about to start
+running, it checks whether some other Ada task R with the same
+priority as T has been suspended due to the loss of priority
+inheritance.  If this is the case, T yields and is placed at the end of
+its priority queue.  When R arrives at the front of the queue it
+executes.
+
+Note that this simple scheme preserves the relative order of the tasks
+that were ready to execute in the priority queue where R has been
+placed at the end.
+
+.. Support_for_Locking_Policies
+
+Support for Locking Policies
+----------------------------
+
+This section specifies which policies specified by pragma Locking_Policy
+are supported on which platforms.
+
+GNAT supports the standard ``Ceiling_Locking`` policy, and the
+implementation defined ``Inheritance_Locking`` and
+``Concurrent_Readers_Locking`` policies.
+
+``Ceiling_Locking`` is supported on all platforms if the operating system
+supports it. In particular, ``Ceiling_Locking`` is not supported on
+VxWorks.
+``Inheritance_Locking`` is supported on
+Linux,
+Darwin (Mac OS X),
+LynxOS 178,
+and VxWorks.
+``Concurrent_Readers_Locking`` is supported on Linux.
+
+Notes about ``Ceiling_Locking`` on Linux:
+If the process is running as 'root', ceiling locking is used.
+If the capabilities facility is installed
+("sudo apt-get --assume-yes install libcap-dev" on Ubuntu,
+for example),
+and the program is linked against that library
+("-largs -lcap"),
+and the executable file has the cap_sys_nice capability
+("sudo /sbin/setcap cap_sys_nice=ep executable_file_name"),
+then ceiling locking is used.
+Otherwise, the ``Ceiling_Locking`` policy is ignored.
+
+.. _GNAT_Implementation_of_Shared_Passive_Packages:
+
+GNAT Implementation of Shared Passive Packages
+==============================================
+
+.. index:: Shared passive packages
+
+GNAT fully implements the :index:`pragma <pragma Shared_Passive>`
+``Shared_Passive`` for
+the purpose of designating shared passive packages.
+This allows the use of passive partitions in the
+context described in the Ada Reference Manual; i.e., for communication
+between separate partitions of a distributed application using the
+features in Annex E.
+
+.. index:: Annex E
+
+.. index:: Distribution Systems Annex
+
+However, the implementation approach used by GNAT provides for more
+extensive usage as follows:
+
+*Communication between separate programs*
+  This allows separate programs to access the data in passive
+  partitions, using protected objects for synchronization where
+  needed. The only requirement is that the two programs have a
+  common shared file system. It is even possible for programs
+  running on different machines with different architectures
+  (e.g., different endianness) to communicate via the data in
+  a passive partition.
+
+*Persistence between program runs*
+  The data in a passive package can persist from one run of a
+  program to another, so that a later program sees the final
+  values stored by a previous run of the same program.
+
+The implementation approach used is to store the data in files. A
+separate stream file is created for each object in the package, and
+an access to an object causes the corresponding file to be read or
+written.
+
+.. index:: SHARED_MEMORY_DIRECTORY environment variable
+
+The environment variable ``SHARED_MEMORY_DIRECTORY`` should be
+set to the directory to be used for these files.
+The files in this directory
+have names that correspond to their fully qualified names. For
+example, if we have the package
+
+.. code-block:: ada
+
+  package X is
+    pragma Shared_Passive (X);
+    Y : Integer;
+    Z : Float;
+  end X;
+
+and the environment variable is set to ``/stemp/``, then the files created
+will have the names:
+
+::
+
+  /stemp/x.y
+  /stemp/x.z
+
+
+These files are created when a value is initially written to the object, and
+the files are retained until manually deleted. This provides the persistence
+semantics. If no file exists, it means that no partition has assigned a value
+to the variable; in this case the initial value declared in the package
+will be used. This model ensures that there are no issues in synchronizing
+the elaboration process, since elaboration of passive packages elaborates the
+initial values, but does not create the files.
+
+The files are written using normal ``Stream_IO`` access.
+If you want to be able
+to communicate between programs or partitions running on different
+architectures, then you should use the XDR versions of the stream attribute
+routines, since these are architecture independent.
+
+If active synchronization is required for access to the variables in the
+shared passive package, then as described in the Ada Reference Manual, the
+package may contain protected objects used for this purpose. In this case
+a lock file (whose name is :file:`___lock` (three underscores)
+is created in the shared memory directory.
+
+.. index:: ___lock file (for shared passive packages)
+
+This is used to provide the required locking
+semantics for proper protected object synchronization.
+
+GNAT supports shared passive packages on all platforms
+except for OpenVMS.
+
+.. _Code_Generation_for_Array_Aggregates:
+
+Code Generation for Array Aggregates
+====================================
+
+Aggregates have a rich syntax and allow the user to specify the values of
+complex data structures by means of a single construct.  As a result, the
+code generated for aggregates can be quite complex and involve loops, case
+statements and multiple assignments.  In the simplest cases, however, the
+compiler will recognize aggregates whose components and constraints are
+fully static, and in those cases the compiler will generate little or no
+executable code.  The following is an outline of the code that GNAT generates
+for various aggregate constructs.  For further details, you will find it
+useful to examine the output produced by the -gnatG flag to see the expanded
+source that is input to the code generator.  You may also want to examine
+the assembly code generated at various levels of optimization.
+
+The code generated for aggregates depends on the context, the component values,
+and the type.  In the context of an object declaration the code generated is
+generally simpler than in the case of an assignment.  As a general rule, static
+component values and static subtypes also lead to simpler code.
+
+.. _Static_constant_aggregates_with_static_bounds:
+
+Static constant aggregates with static bounds
+---------------------------------------------
+
+For the declarations:
+
+.. code-block:: ada
+
+      type One_Dim is array (1..10) of integer;
+      ar0 : constant One_Dim := (1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
+
+
+GNAT generates no executable code: the constant ar0 is placed in static memory.
+The same is true for constant aggregates with named associations:
+
+
+.. code-block:: ada
+
+      Cr1 : constant One_Dim := (4 => 16, 2 => 4, 3 => 9, 1 => 1, 5 .. 10 => 0);
+      Cr3 : constant One_Dim := (others => 7777);
+
+
+The same is true for multidimensional constant arrays such as:
+
+.. code-block:: ada
+
+      type two_dim is array (1..3, 1..3) of integer;
+      Unit : constant two_dim := ( (1,0,0), (0,1,0), (0,0,1));
+
+
+The same is true for arrays of one-dimensional arrays: the following are
+static:
+
+
+.. code-block:: ada
+
+  type ar1b  is array (1..3) of boolean;
+  type ar_ar is array (1..3) of ar1b;
+  None  : constant ar1b := (others => false);     --  fully static
+  None2 : constant ar_ar := (1..3 => None);       --  fully static
+
+
+However, for multidimensional aggregates with named associations, GNAT will
+generate assignments and loops, even if all associations are static.  The
+following two declarations generate a loop for the first dimension, and
+individual component assignments for the second dimension:
+
+
+.. code-block:: ada
+
+  Zero1: constant two_dim := (1..3 => (1..3 => 0));
+  Zero2: constant two_dim := (others => (others => 0));
+
+
+.. _Constant_aggregates_with_unconstrained_nominal_types:
+
+Constant aggregates with unconstrained nominal types
+----------------------------------------------------
+
+In such cases the aggregate itself establishes the subtype, so that
+associations with ``others`` cannot be used.  GNAT determines the
+bounds for the actual subtype of the aggregate, and allocates the
+aggregate statically as well.  No code is generated for the following:
+
+
+.. code-block:: ada
+
+      type One_Unc is array (natural range <>) of integer;
+      Cr_Unc : constant One_Unc := (12,24,36);
+
+
+.. _Aggregates_with_static_bounds:
+
+Aggregates with static bounds
+-----------------------------
+
+In all previous examples the aggregate was the initial (and immutable) value
+of a constant.  If the aggregate initializes a variable, then code is generated
+for it as a combination of individual assignments and loops over the target
+object.  The declarations
+
+
+.. code-block:: ada
+
+         Cr_Var1 : One_Dim := (2, 5, 7, 11, 0, 0, 0, 0, 0, 0);
+         Cr_Var2 : One_Dim := (others > -1);
+
+
+generate the equivalent of
+
+
+.. code-block:: ada
+
+         Cr_Var1 (1) := 2;
+         Cr_Var1 (2) := 3;
+         Cr_Var1 (3) := 5;
+         Cr_Var1 (4) := 11;
+
+         for I in Cr_Var2'range loop
+            Cr_Var2 (I) := -1;
+         end loop;
+
+
+.. _Aggregates_with_nonstatic_bounds:
+
+Aggregates with nonstatic bounds
+---------------------------------
+
+If the bounds of the aggregate are not statically compatible with the bounds
+of the nominal subtype  of the target, then constraint checks have to be
+generated on the bounds.  For a multidimensional array, constraint checks may
+have to be applied to sub-arrays individually, if they do not have statically
+compatible subtypes.
+
+.. _Aggregates_in_assignment_statements:
+
+Aggregates in assignment statements
+-----------------------------------
+
+In general, aggregate assignment requires the construction of a temporary,
+and a copy from the temporary to the target of the assignment.  This is because
+it is not always possible to convert the assignment into a series of individual
+component assignments.  For example, consider the simple case:
+
+
+.. code-block:: ada
+
+          A := (A(2), A(1));
+
+
+This cannot be converted into:
+
+
+.. code-block:: ada
+
+          A(1) := A(2);
+          A(2) := A(1);
+
+
+So the aggregate has to be built first in a separate location, and then
+copied into the target.  GNAT recognizes simple cases where this intermediate
+step is not required, and the assignments can be performed in place, directly
+into the target.  The following sufficient criteria are applied:
+
+*
+  The bounds of the aggregate are static, and the associations are static.
+*
+  The components of the aggregate are static constants, names of
+  simple variables that are not renamings, or expressions not involving
+  indexed components whose operands obey these rules.
+
+If any of these conditions are violated, the aggregate will be built in
+a temporary (created either by the front-end or the code generator) and then
+that temporary will be copied onto the target.
+
+.. _The_Size_of_Discriminated_Records_with_Default_Discriminants:
+
+The Size of Discriminated Records with Default Discriminants
+============================================================
+
+If a discriminated type ``T`` has discriminants with default values, it is
+possible to declare an object of this type without providing an explicit
+constraint:
+
+
+.. code-block:: ada
+
+  type Size is range 1..100;
+
+  type Rec (D : Size := 15) is record
+     Name : String (1..D);
+  end T;
+
+  Word : Rec;
+
+
+Such an object is said to be *unconstrained*.
+The discriminant of the object
+can be modified by a full assignment to the object, as long as it preserves the
+relation between the value of the discriminant, and the value of the components
+that depend on it:
+
+
+.. code-block:: ada
+
+  Word := (3, "yes");
+
+  Word := (5, "maybe");
+
+  Word := (5, "no"); -- raises Constraint_Error
+
+In order to support this behavior efficiently, an unconstrained object is
+given the maximum size that any value of the type requires. In the case
+above, ``Word`` has storage for the discriminant and for
+a ``String`` of length 100.
+It is important to note that unconstrained objects do not require dynamic
+allocation. It would be an improper implementation to place on the heap those
+components whose size depends on discriminants. (This improper implementation
+was used by some Ada83 compilers, where the ``Name`` component above
+would have
+been stored as a pointer to a dynamic string). Following the principle that
+dynamic storage management should never be introduced implicitly,
+an Ada compiler should reserve the full size for an unconstrained declared
+object, and place it on the stack.
+
+This maximum size approach
+has been a source of surprise to some users, who expect the default
+values of the discriminants to determine the size reserved for an
+unconstrained object: "If the default is 15, why should the object occupy
+a larger size?"
+The answer, of course, is that the discriminant may be later modified,
+and its full range of values must be taken into account. This is why the
+declaration:
+
+
+.. code-block:: ada
+
+  type Rec (D : Positive := 15) is record
+     Name : String (1..D);
+  end record;
+
+  Too_Large : Rec;
+
+is flagged by the compiler with a warning:
+an attempt to create ``Too_Large`` will raise ``Storage_Error``,
+because the required size includes ``Positive'Last``
+bytes. As the first example indicates, the proper approach is to declare an
+index type of 'reasonable' range so that unconstrained objects are not too
+large.
+
+One final wrinkle: if the object is declared to be ``aliased``, or if it is
+created in the heap by means of an allocator, then it is *not*
+unconstrained:
+it is constrained by the default values of the discriminants, and those values
+cannot be modified by full assignment. This is because in the presence of
+aliasing all views of the object (which may be manipulated by different tasks,
+say) must be consistent, so it is imperative that the object, once created,
+remain invariant.
+
+.. _Strict_Conformance_to_the_Ada_Reference_Manual:
+
+Strict Conformance to the Ada Reference Manual
+==============================================
+
+The dynamic semantics defined by the Ada Reference Manual impose a set of
+run-time checks to be generated. By default, the GNAT compiler will insert many
+run-time checks into the compiled code, including most of those required by the
+Ada Reference Manual. However, there are two checks that are not enabled in
+the default mode for efficiency reasons: checks for access before elaboration
+on subprogram calls, and stack overflow checking (most operating systems do not
+perform this check by default).
+
+Strict conformance to the Ada Reference Manual can be achieved by adding two
+compiler options for dynamic checks for access-before-elaboration on subprogram
+calls and generic instantiations (*-gnatE*), and stack overflow checking
+(*-fstack-check*).
+
+Note that the result of a floating point arithmetic operation in overflow and
+invalid situations, when the ``Machine_Overflows`` attribute of the result
+type is ``False``, is to generate IEEE NaN and infinite values. This is the
+case for machines compliant with the IEEE floating-point standard, but on
+machines that are not fully compliant with this standard, such as Alpha, the
+*-mieee* compiler flag must be used for achieving IEEE confirming
+behavior (although at the cost of a significant performance penalty), so
+infinite and NaN values are properly generated.