mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
ada: Update GNAT UG
Also add some LLVM-specific information. gcc/ada/ChangeLog: * doc/gnat_ugn/about_this_guide.rst: Numerous changes to language and style and add some LLVM-specific information. * doc/gnat_ugn/elaboration_order_handling_in_gnat.rst: Likewise. * doc/gnat_ugn/example_of_binder_output.rst: Likewise. * doc/gnat_ugn/getting_started_with_gnat.rst: Likewise. * doc/gnat_ugn/gnat_and_program_execution.rst: Likewise. * doc/gnat_ugn/gnat_utility_programs.rst: Likewise. * doc/gnat_ugn/inline_assembler.rst: Likewise. * doc/gnat_ugn/platform_specific_information.rst: Likewise. * doc/gnat_ugn/the_gnat_compilation_model.rst: Likewise. * gnat_ugn.texi: Regenerate.
This commit is contained in:
parent
8af9169fcf
commit
257d0d7769
@ -14,13 +14,13 @@ toolset for the full Ada programming language.
|
||||
It documents the features of the compiler and tools, and explains
|
||||
how to use them to build Ada applications.
|
||||
|
||||
GNAT implements Ada 95, Ada 2005, Ada 2012, and Ada 202x, and it may also be
|
||||
invoked in Ada 83 compatibility mode.
|
||||
By default, GNAT assumes Ada 2012, but you can override with a
|
||||
compiler switch (:ref:`Compiling_Different_Versions_of_Ada`)
|
||||
to explicitly specify the language version.
|
||||
Throughout this manual, references to 'Ada' without a year suffix
|
||||
apply to all Ada versions of the language, starting with Ada 95.
|
||||
GNAT implements Ada 95, Ada 2005, Ada 2012, and Ada 2022. You may
|
||||
also invoke it in Ada 83 compatibility mode. By default, GNAT assumes
|
||||
Ada 2012, but you can use a compiler switch
|
||||
(:ref:`Compiling_Different_Versions_of_Ada`) to explicitly specify the
|
||||
language version. Throughout this manual, references to 'Ada' without
|
||||
a year suffix apply to all versions of the Ada language starting with
|
||||
Ada 95.
|
||||
|
||||
What This Guide Contains
|
||||
========================
|
||||
@ -130,10 +130,10 @@ in this guide:
|
||||
|
||||
and then shown this way.
|
||||
|
||||
* Commands that are entered by the user are shown as preceded by a prompt string
|
||||
* Commands that you enter are shown as preceded by a prompt string
|
||||
comprising the ``$`` character followed by a space.
|
||||
|
||||
* Full file names are shown with the '/' character
|
||||
as the directory separator; e.g., :file:`parent-dir/subdir/myfile.adb`.
|
||||
If you are using GNAT on a Windows platform, please note that
|
||||
the '\\' character should be used instead.
|
||||
you should use the '\\' character instead.
|
||||
|
@ -17,8 +17,8 @@ Elaboration Order Handling in GNAT
|
||||
.. index:: Order of elaboration
|
||||
.. index:: Elaboration control
|
||||
|
||||
This appendix describes the handling of elaboration code in Ada and GNAT, and
|
||||
discusses how the order of elaboration of program units can be controlled in
|
||||
This appendix describes the handling of elaboration code in Ada and GNAT and
|
||||
discusses how you can control the order of elaboration of program units in
|
||||
GNAT, either automatically or with explicit programming features.
|
||||
|
||||
.. _Elaboration_Code:
|
||||
@ -36,7 +36,7 @@ initializing data. These sections are referred to as **elaboration code**.
|
||||
Elaboration code is executed as follows:
|
||||
|
||||
* All partitions of an Ada program are executed in parallel with one another,
|
||||
possibly in a separate address space, and possibly on a separate computer.
|
||||
possibly in a separate address space and possibly on a separate computer.
|
||||
|
||||
* The execution of a partition involves running the environment task for that
|
||||
partition.
|
||||
@ -71,8 +71,9 @@ In addition to the Ada terminology, this appendix defines the following terms:
|
||||
|
||||
* *Target*
|
||||
|
||||
A construct elaborated by a scenario is referred to as *elaboration target*
|
||||
or simply **target**. GNAT recognizes the following targets:
|
||||
A construct elaborated by a scenario is referred to as an
|
||||
*elaboration target* or simply a **target**. GNAT recognizes the
|
||||
following targets:
|
||||
|
||||
- For ``'Access`` of entries, operators, and subprograms, the target is the
|
||||
entry, operator, or subprogram being aliased.
|
||||
@ -188,7 +189,8 @@ factors:
|
||||
|
||||
* invocations performed in elaboration code
|
||||
|
||||
A program may have several elaboration orders depending on its structure.
|
||||
A program may have several possible elaboration orders depending on
|
||||
its structure:
|
||||
|
||||
.. code-block:: ada
|
||||
|
||||
@ -256,7 +258,7 @@ Ada states that a total elaboration order must exist, but it does not define
|
||||
what this order is. A compiler is thus tasked with choosing a suitable
|
||||
elaboration order which satisfies the dependencies imposed by |with| clauses,
|
||||
unit categorization, elaboration-control pragmas, and invocations performed in
|
||||
elaboration code. Ideally an order that avoids ABE problems should be chosen,
|
||||
elaboration code. Ideally, an order that avoids ABE problems should be chosen,
|
||||
however a compiler may not always find such an order due to complications with
|
||||
respect to control and data flow.
|
||||
|
||||
@ -277,7 +279,7 @@ provides three lines of defense:
|
||||
|
||||
* *Dynamic semantics*
|
||||
|
||||
Dynamic checks are performed at run time, to ensure that a target is
|
||||
Dynamic checks are performed at run time to ensure that a target is
|
||||
elaborated prior to a scenario that invokes it, thus avoiding ABE problems.
|
||||
A failed run-time check raises exception ``Program_Error``. The following
|
||||
restrictions apply:
|
||||
@ -304,7 +306,7 @@ provides three lines of defense:
|
||||
|
||||
* *Elaboration control*
|
||||
|
||||
Pragmas are provided for the programmer to specify the desired elaboration
|
||||
Ada provides pragmas for you to specify the desired elaboration
|
||||
order.
|
||||
|
||||
.. _Controlling_the_Elaboration_Order_in_Ada:
|
||||
@ -312,12 +314,12 @@ provides three lines of defense:
|
||||
Controlling the Elaboration Order in Ada
|
||||
========================================
|
||||
|
||||
Ada provides several idioms and pragmas to aid the programmer with specifying
|
||||
the desired elaboration order and avoiding ABE problems altogether.
|
||||
Ada provides several idioms and pragmas to aid you in specifying your
|
||||
desired elaboration order and avoiding ABE problems.
|
||||
|
||||
* *Packages without a body*
|
||||
|
||||
A library package which does not require a completing body does not suffer
|
||||
A library package that does not require a completing body does not suffer
|
||||
from ABE problems.
|
||||
|
||||
.. code-block:: ada
|
||||
@ -391,9 +393,9 @@ the desired elaboration order and avoiding ABE problems altogether.
|
||||
body of Server
|
||||
spec of Client
|
||||
|
||||
because the spec of ``Server`` must be elaborated prior to ``Client`` by
|
||||
virtue of the |with| clause, and in addition the body of ``Server`` must be
|
||||
elaborated immediately after the spec of ``Server``.
|
||||
because the spec of ``Server`` must be elaborated prior to
|
||||
``Client`` by virtue of the |with| clause and the body of ``Server``
|
||||
must be elaborated immediately after the spec of ``Server``.
|
||||
|
||||
Removing pragma ``Elaborate_Body`` could result in the following incorrect
|
||||
elaboration order:
|
||||
@ -420,7 +422,7 @@ depend on.
|
||||
|
||||
* *pragma Elaborate (Unit)*
|
||||
|
||||
Pragma ``Elaborate`` can be placed in the context clauses of a unit, after a
|
||||
You can place pragma ``Elaborate`` in the context clauses of a unit, after a
|
||||
|with| clause. It guarantees that both the spec and body of its argument will
|
||||
be elaborated prior to the unit with the pragma. Note that other unrelated
|
||||
units may be elaborated in between the spec and the body.
|
||||
@ -473,11 +475,12 @@ depend on.
|
||||
|
||||
* *pragma Elaborate_All (Unit)*
|
||||
|
||||
Pragma ``Elaborate_All`` is placed in the context clauses of a unit, after
|
||||
a |with| clause. It guarantees that both the spec and body of its argument
|
||||
will be elaborated prior to the unit with the pragma, as well as all units
|
||||
|withed| by the spec and body of the argument, recursively. Note that other
|
||||
unrelated units may be elaborated in between the spec and the body.
|
||||
You can place pragma ``Elaborate_All`` in the context clauses of a
|
||||
unit, after a |with| clause. It guarantees that both the spec and
|
||||
body of its argument will be elaborated prior to the unit with the
|
||||
pragma as well as all units |withed| by the spec and body of the
|
||||
argument, recursively. Note that other unrelated units may be
|
||||
elaborated in between the spec and the body.
|
||||
|
||||
.. code-block:: ada
|
||||
|
||||
@ -566,12 +569,12 @@ the server unit requires a body and does not have pragma Pure, Preelaborate,
|
||||
or Elaborate_Body, then the client unit should have pragma Elaborate or
|
||||
Elaborate_All for the server unit.*
|
||||
|
||||
If the rule outlined above is not followed, then a program may fall in one of
|
||||
the following states:
|
||||
If you do not follow the rule outlined above, a program may fall in one of
|
||||
the following ways:
|
||||
|
||||
* *No elaboration order exists*
|
||||
|
||||
In this case a compiler must diagnose the situation, and refuse to build an
|
||||
In this case a compiler must diagnose the situation and refuse to build an
|
||||
executable program.
|
||||
|
||||
* *One or more incorrect elaboration orders exist*
|
||||
@ -581,17 +584,17 @@ the following states:
|
||||
|
||||
* *Several elaboration orders exist, some correct, some incorrect*
|
||||
|
||||
In this case the programmer has not controlled the elaboration order. As a
|
||||
result, a compiler may or may not pick one of the correct orders, and the
|
||||
In this case, you have not controlled the elaboration order. As a
|
||||
result, a compiler may or may not pick one of the correct orders and the
|
||||
program may or may not raise ``Program_Error`` when it is run. This is the
|
||||
worst possible state because the program may fail on another compiler, or
|
||||
even another version of the same compiler.
|
||||
worst possible state because the program may fail on another compiler or
|
||||
even a different version of the same compiler.
|
||||
|
||||
* *One or more correct orders exist*
|
||||
|
||||
In this case a compiler can build an executable program, and the program is
|
||||
In this case a compiler can build an executable program and the program is
|
||||
run successfully. This state may be guaranteed by following the outlined
|
||||
rules, or may be the result of good program architecture.
|
||||
rules or may be the result of good program architecture.
|
||||
|
||||
Note that one additional advantage of using ``Elaborate`` and ``Elaborate_All``
|
||||
is that the program continues to stay in the last state (one or more correct
|
||||
@ -602,9 +605,9 @@ orders exist) even if maintenance changes the bodies of targets.
|
||||
Controlling the Elaboration Order in GNAT
|
||||
=========================================
|
||||
|
||||
In addition to Ada semantics and rules synthesized from them, GNAT offers
|
||||
three elaboration models to aid the programmer with specifying the correct
|
||||
elaboration order and to diagnose elaboration problems.
|
||||
In addition to Ada semantics and rules synthesized from them, GNAT
|
||||
offers three elaboration models to aid you in specifying the correct
|
||||
elaboration order and in diagnosing elaboration problems.
|
||||
|
||||
.. index:: Dynamic elaboration model
|
||||
|
||||
@ -631,7 +634,7 @@ elaboration order and to diagnose elaboration problems.
|
||||
assumptions stated above. An order obtained using the dynamic model may fail
|
||||
an ABE check at run time when GNAT ignored an invocation.
|
||||
|
||||
The dynamic model is enabled with compiler switch :switch:`-gnatE`.
|
||||
You enable the dynamic model with the compiler switch :switch:`-gnatE`.
|
||||
|
||||
.. index:: Static elaboration model
|
||||
|
||||
@ -678,24 +681,25 @@ elaboration order and to diagnose elaboration problems.
|
||||
following legacy models:
|
||||
|
||||
- `Legacy elaboration-checking model` available in pre-18.x versions of GNAT.
|
||||
This model is enabled with compiler switch :switch:`-gnatH`.
|
||||
You can enable this model with compiler switch :switch:`-gnatH`.
|
||||
|
||||
- `Legacy elaboration-order model` available in pre-20.x versions of GNAT.
|
||||
This model is enabled with binder switch :switch:`-H`.
|
||||
You can enable this model with binder switch :switch:`-H`.
|
||||
|
||||
.. index:: Relaxed elaboration mode
|
||||
|
||||
The dynamic, legacy, and static models can be relaxed using compiler switch
|
||||
:switch:`-gnatJ`, making them more permissive. Note that in this mode, GNAT
|
||||
may not diagnose certain elaboration issues or install run-time checks.
|
||||
You can relax the dynamic, legacy, and static models by specifying
|
||||
compiler switch :switch:`-gnatJ`, which makes them more permissive. Note
|
||||
that in this mode, GNAT may not diagnose certain elaboration issues or
|
||||
install run-time checks.
|
||||
|
||||
.. _Mixing_Elaboration_Models:
|
||||
|
||||
Mixing Elaboration Models
|
||||
=========================
|
||||
|
||||
It is possible to mix units compiled with a different elaboration model,
|
||||
however the following rules must be observed:
|
||||
You can mix units compiled with different elaboration models. However
|
||||
you must observe the following rules:
|
||||
|
||||
* A client unit compiled with the dynamic model can only |with| a server unit
|
||||
that meets at least one of the following criteria:
|
||||
@ -718,7 +722,7 @@ violated, the binder emits a warning:
|
||||
warning: "x.ads" has dynamic elaboration checks and with's
|
||||
warning: "y.ads" which has static elaboration checks
|
||||
|
||||
The warnings can be suppressed by binder switch :switch:`-ws`.
|
||||
You can suppress these warnings by specifying binder switch :switch:`-ws`.
|
||||
|
||||
.. _ABE_Diagnostics:
|
||||
|
||||
@ -729,14 +733,14 @@ GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios
|
||||
that invoke internal targets, regardless of whether the dynamic, SPARK, or
|
||||
static model is in effect.
|
||||
|
||||
Note that GNAT emits warnings rather than hard errors whenever it encounters an
|
||||
Note that GNAT emits warnings rather than errors whenever it encounters an
|
||||
elaboration problem. This is because the elaboration model in effect may be too
|
||||
conservative, or a particular scenario may not be invoked due conditional
|
||||
execution. The warnings can be suppressed selectively with ``pragma Warnings
|
||||
conservative or a particular scenario may not be invoked due to conditional
|
||||
execution. You can selectively suppress the warnings with ``pragma Warnings
|
||||
(Off)`` or globally with compiler switch :switch:`-gnatwL`.
|
||||
|
||||
A *guaranteed ABE* arises when the body of a target is not elaborated early
|
||||
enough, and causes *all* scenarios that directly invoke the target to fail.
|
||||
enough and causes *all* scenarios that directly invoke the target to fail.
|
||||
|
||||
.. code-block:: ada
|
||||
|
||||
@ -763,7 +767,7 @@ the declaration of ``Val``. This invokes function ``ABE``, however the body of
|
||||
>>> warning: Program_Error will be raised at run time
|
||||
|
||||
A *conditional ABE* arises when the body of a target is not elaborated early
|
||||
enough, and causes *some* scenarios that directly invoke the target to fail.
|
||||
enough and causes *some* scenarios that directly invoke the target to fail.
|
||||
|
||||
.. code-block:: ada
|
||||
|
||||
@ -821,8 +825,8 @@ SPARK Diagnostics
|
||||
=================
|
||||
|
||||
GNAT enforces the SPARK rules of elaboration as defined in the SPARK Reference
|
||||
Manual section 7.7 when compiler switch :switch:`-gnatd.v` is in effect. Note
|
||||
that GNAT emits hard errors whenever it encounters a violation of the SPARK
|
||||
Manual section 7.7 when you specify compiler switch :switch:`-gnatd.v`. Note
|
||||
that GNAT emits errors whenever it encounters a violation of the SPARK
|
||||
rules.
|
||||
|
||||
::
|
||||
@ -938,7 +942,7 @@ subprograms, where the program controls the order of initialization explicitly.
|
||||
Although this is the most desirable option, it may be impractical and involve
|
||||
too much modification, especially in the case of complex legacy code.
|
||||
|
||||
When faced with an elaboration circularity, the programmer should also consider
|
||||
When faced with an elaboration circularity, you should also consider
|
||||
the tactics given in the suggestions section of the circularity diagnostic.
|
||||
Depending on the units involved in the circularity, their |with| clauses,
|
||||
purity, preelaborability, presence of elaboration-control pragmas and
|
||||
@ -951,10 +955,9 @@ following tactics to eliminate the circularity:
|
||||
|
||||
remove pragma Elaborate for unit "..." in unit "..."
|
||||
|
||||
This tactic is suggested when the binder has determined that pragma
|
||||
``Elaborate``:
|
||||
The binder suggests this tactic when it has determined that:
|
||||
|
||||
- Prevents a set of units from being elaborated.
|
||||
- pragma ``Elaborate`` prevents a set of units from being elaborated.
|
||||
|
||||
- The removal of the pragma will not eliminate the semantic effects of the
|
||||
pragma. In other words, the argument of the pragma will still be elaborated
|
||||
@ -962,7 +965,7 @@ following tactics to eliminate the circularity:
|
||||
|
||||
- The removal of the pragma will enable the successful ordering of the units.
|
||||
|
||||
The programmer should remove the pragma as advised, and rebuild the program.
|
||||
You should remove the pragma as advised and rebuild the program.
|
||||
|
||||
* Pragma Elaborate_All elimination
|
||||
|
||||
@ -970,10 +973,10 @@ following tactics to eliminate the circularity:
|
||||
|
||||
remove pragma Elaborate_All for unit "..." in unit "..."
|
||||
|
||||
This tactic is suggested when the binder has determined that pragma
|
||||
``Elaborate_All``:
|
||||
The binder suggests this tactic when it has determined that:
|
||||
|
||||
- Prevents a set of units from being elaborated.
|
||||
- pragma ``Elaborate_All`` prevents a set of units from being
|
||||
elaborated.
|
||||
|
||||
- The removal of the pragma will not eliminate the semantic effects of the
|
||||
pragma. In other words, the argument of the pragma along with its |with|
|
||||
@ -981,7 +984,7 @@ following tactics to eliminate the circularity:
|
||||
|
||||
- The removal of the pragma will enable the successful ordering of the units.
|
||||
|
||||
The programmer should remove the pragma as advised, and rebuild the program.
|
||||
You should remove the pragma as advised and rebuild the program.
|
||||
|
||||
* Pragma Elaborate_All downgrade
|
||||
|
||||
@ -989,12 +992,12 @@ following tactics to eliminate the circularity:
|
||||
|
||||
change pragma Elaborate_All for unit "..." to Elaborate in unit "..."
|
||||
|
||||
This tactic is always suggested with the pragma ``Elaborate_All`` elimination
|
||||
tactic. It offers a different alternative of guaranteeing that the argument
|
||||
of the pragma will still be elaborated prior to the unit containing the
|
||||
pragma.
|
||||
The binder always suggests this tactic when it suggests the pragma
|
||||
``Elaborate_All`` elimination tactic. It offers a different
|
||||
alternative of guaranteeing that the argument of the pragma will
|
||||
still be elaborated prior to the unit containing the pragma.
|
||||
|
||||
The programmer should update the pragma as advised, and rebuild the program.
|
||||
You should update the pragma as advised and rebuild the program.
|
||||
|
||||
* Pragma Elaborate_Body elimination
|
||||
|
||||
@ -1002,10 +1005,9 @@ following tactics to eliminate the circularity:
|
||||
|
||||
remove pragma Elaborate_Body in unit "..."
|
||||
|
||||
This tactic is suggested when the binder has determined that pragma
|
||||
``Elaborate_Body``:
|
||||
The binder suggests this tactic when it has determined that:
|
||||
|
||||
- Prevents a set of units from being elaborated.
|
||||
- pragma ``Elaborate_Body`` prevents a set of units from being elaborated.
|
||||
|
||||
- The removal of the pragma will enable the successful ordering of the units.
|
||||
|
||||
@ -1013,7 +1015,8 @@ following tactics to eliminate the circularity:
|
||||
other purposes, such as guaranteeing the initialization of a variable
|
||||
declared in the spec by elaboration code in the body.
|
||||
|
||||
The programmer should remove the pragma as advised, and rebuild the program.
|
||||
If the pragma is not required for another purpose, you should remove
|
||||
the pragma as advised and rebuild the program.
|
||||
|
||||
* Use of pragma Restrictions
|
||||
|
||||
@ -1021,7 +1024,7 @@ following tactics to eliminate the circularity:
|
||||
|
||||
use pragma Restrictions (No_Entry_Calls_In_Elaboration_Code)
|
||||
|
||||
This tactic is suggested when the binder has determined that a task
|
||||
The binder suggests this tactic when it has determined that a task
|
||||
activation at elaboration time:
|
||||
|
||||
- Prevents a set of units from being elaborated.
|
||||
@ -1046,16 +1049,16 @@ following tactics to eliminate the circularity:
|
||||
- The use of the dynamic model will enable the successful ordering of the
|
||||
units.
|
||||
|
||||
The programmer has two options:
|
||||
You have two options:
|
||||
|
||||
- Determine the units involved in the invocation using the detailed
|
||||
invocation information, and add compiler switch :switch:`-gnatE` to the
|
||||
compilation arguments of selected files only. This approach will yield
|
||||
invocation information and add compiler switch :switch:`-gnatE` to the
|
||||
compilation arguments of those units only. This approach will yield
|
||||
safer elaboration orders compared to the other option because it will
|
||||
minimize the opportunities presented to the dynamic model for ignoring
|
||||
invocations.
|
||||
|
||||
- Add compiler switch :switch:`-gnatE` to the general compilation arguments.
|
||||
- Add compiler switch :switch:`-gnatE` to the global compilation arguments.
|
||||
|
||||
* Use of detailed invocation information
|
||||
|
||||
@ -1063,13 +1066,13 @@ following tactics to eliminate the circularity:
|
||||
|
||||
use detailed invocation information (compiler switch -gnatd_F)
|
||||
|
||||
This tactic is always suggested with the use of the dynamic model tactic. It
|
||||
causes the circularity section of the circularity diagnostic to describe the
|
||||
flow of elaboration code from a unit to a unit, enumerating all such paths in
|
||||
the process.
|
||||
The binder always suggests this tactic when it suggests use of the
|
||||
dynamic model tactic. It causes the circularity section of the
|
||||
circularity diagnostic to describe the flow of elaboration code from
|
||||
a unit to a unit, enumerating all such paths in the process.
|
||||
|
||||
The programmer should analyze this information to determine which units
|
||||
should be compiled with the dynamic model.
|
||||
You should analyze this information to determine which units should
|
||||
be compiled with the dynamic model.
|
||||
|
||||
* Forced-dependency elimination
|
||||
|
||||
@ -1077,16 +1080,16 @@ following tactics to eliminate the circularity:
|
||||
|
||||
remove the dependency of unit "..." on unit "..." from the argument of switch -f
|
||||
|
||||
This tactic is suggested when the binder has determined that a dependency
|
||||
present in the forced-elaboration-order file indicated by binder switch
|
||||
:switch:`-f`:
|
||||
The binder suggests this tactic when it has determined that a
|
||||
dependency present in the forced-elaboration-order file indicated by
|
||||
binder switch :switch:`-f`:
|
||||
|
||||
- Prevents a set of units from being elaborated.
|
||||
|
||||
- The removal of the dependency will enable the successful ordering of the
|
||||
units.
|
||||
|
||||
The programmer should edit the forced-elaboration-order file, remove the
|
||||
You should edit the forced-elaboration-order file, remove the
|
||||
dependency, and rebind the program.
|
||||
|
||||
* All forced-dependency elimination
|
||||
@ -1095,11 +1098,11 @@ following tactics to eliminate the circularity:
|
||||
|
||||
remove switch -f
|
||||
|
||||
This tactic is suggested in case editing the forced-elaboration-order file is
|
||||
not an option.
|
||||
The binder suggests this tactic when editing the
|
||||
forced-elaboration-order file is not an option.
|
||||
|
||||
The programmer should remove binder switch :switch:`-f` from the binder
|
||||
arguments, and rebind.
|
||||
You should remove binder switch :switch:`-f` from the binder
|
||||
arguments and rebind.
|
||||
|
||||
* Multiple-circularities diagnostic
|
||||
|
||||
@ -1107,16 +1110,16 @@ following tactics to eliminate the circularity:
|
||||
|
||||
diagnose all circularities (binder switch -d_C)
|
||||
|
||||
By default, the binder will diagnose only the highest-precedence circularity.
|
||||
If the program contains multiple circularities, the binder will suggest the
|
||||
use of binder switch :switch:`-d_C` in order to obtain the diagnostics of all
|
||||
circularities.
|
||||
By default, the binder only diagnoses the highest-precedence
|
||||
circularity. If the program contains multiple circularities, the
|
||||
binder will suggest the use of binder switch :switch:`-d_C` in order
|
||||
to obtain the diagnostics for each circularity.
|
||||
|
||||
The programmer should add binder switch :switch:`-d_C` to the binder
|
||||
arguments, and rebind.
|
||||
You should add binder switch :switch:`-d_C` to the binder arguments
|
||||
and rebind.
|
||||
|
||||
If none of the tactics suggested by the binder eliminate the elaboration
|
||||
circularity, the programmer should consider using one of the legacy elaboration
|
||||
circularity, you should consider using one of the legacy elaboration
|
||||
models, in the following order:
|
||||
|
||||
* Use the pre-20.x legacy elaboration-order model, with binder switch
|
||||
@ -1150,7 +1153,7 @@ the elaboration order chosen by the binder.
|
||||
.. index:: -gnatel (gnat)
|
||||
|
||||
:switch:`-gnatel`
|
||||
Turn on info messages on generated Elaborate[_All] pragmas
|
||||
Turn on informational messages on generated Elaborate[_All] pragmas
|
||||
|
||||
This switch is only applicable to the pre-20.x legacy elaboration models.
|
||||
The post-20.x elaboration model no longer relies on implicitly generated
|
||||
@ -1280,23 +1283,23 @@ the elaboration order chosen by the binder.
|
||||
Summary of Procedures for Elaboration Control
|
||||
=============================================
|
||||
|
||||
A programmer should first compile the program with the default options, using
|
||||
You should first compile the program with the default options, using
|
||||
none of the binder or compiler switches. If the binder succeeds in finding an
|
||||
elaboration order, then apart from possible cases involving dispatching calls
|
||||
and access-to-subprogram types, the program is free of elaboration errors.
|
||||
|
||||
If it is important for the program to be portable to compilers other than GNAT,
|
||||
then the programmer should use compiler switch :switch:`-gnatel` and consider
|
||||
the messages about missing or implicitly created ``Elaborate`` and
|
||||
``Elaborate_All`` pragmas.
|
||||
If it is important for the program to be portable to compilers other
|
||||
than GNAT, you should use compiler switch :switch:`-gnatel` and
|
||||
consider the messages about missing or implicitly created
|
||||
``Elaborate`` and ``Elaborate_All`` pragmas.
|
||||
|
||||
If the binder reports an elaboration circularity, the programmer has several
|
||||
If the binder reports an elaboration circularity, you have several
|
||||
options:
|
||||
|
||||
* Ensure that elaboration warnings are enabled. This will allow the static
|
||||
* Ensure that elaboration warnings are enabled. This allows the static
|
||||
model to output trace information of elaboration issues. The trace
|
||||
information could shed light on previously unforeseen dependencies, as well
|
||||
as their origins. Elaboration warnings are enabled with compiler switch
|
||||
information could shed light on previously unforeseen dependencies as well
|
||||
as their origins. You enable elaboration warnings with compiler switch
|
||||
:switch:`-gnatwl`.
|
||||
|
||||
* Cosider the tactics given in the suggestions section of the circularity
|
||||
|
@ -7,7 +7,7 @@ Example of Binder Output File
|
||||
.. index:: Binder output (example)
|
||||
|
||||
This Appendix displays the source code for the output file
|
||||
generated by *gnatbind* for a simple 'Hello World' program.
|
||||
generated by ``gnatbind`` for a simple 'Hello World' program.
|
||||
Comments have been added for clarification purposes.
|
||||
|
||||
|
||||
@ -24,8 +24,7 @@ Comments have been added for clarification purposes.
|
||||
|
||||
-- The main program saves the parameters (argument count,
|
||||
-- argument values, environment pointer) in global variables
|
||||
-- for later access by other units including
|
||||
-- Ada.Command_Line.
|
||||
-- for later access by other units including Ada.Command_Line.
|
||||
|
||||
gnat_argc : Integer;
|
||||
gnat_argv : System.Address;
|
||||
@ -400,8 +399,8 @@ Comments have been added for clarification purposes.
|
||||
package body ada_main is
|
||||
pragma Warnings (Off);
|
||||
|
||||
-- These values are reference counter associated to units which have
|
||||
-- been elaborated. It is also used to avoid elaborating the
|
||||
-- These values are reference counters associated with units that have
|
||||
-- been elaborated. They are used to avoid elaborating the
|
||||
-- same unit twice.
|
||||
|
||||
E72 : Short_Integer; pragma Import (Ada, E72, "system__os_lib_E");
|
||||
@ -559,8 +558,8 @@ Comments have been added for clarification purposes.
|
||||
-- Now we have the elaboration calls for all units in the partition.
|
||||
-- The Elab_Spec and Elab_Body attributes generate references to the
|
||||
-- implicit elaboration procedures generated by the compiler for
|
||||
-- each unit that requires elaboration. Increment a counter of
|
||||
-- reference for each unit.
|
||||
-- each unit that requires elaboration. Also increment a reference
|
||||
-- counter for each unit.
|
||||
|
||||
System.Soft_Links'Elab_Spec;
|
||||
System.Exception_Table'Elab_Body;
|
||||
@ -625,11 +624,10 @@ Comments have been added for clarification purposes.
|
||||
end adafinal;
|
||||
|
||||
-- We get to the main program of the partition by using
|
||||
-- pragma Import because if we try to with the unit and
|
||||
-- call it Ada style, then not only do we waste time
|
||||
-- recompiling it, but also, we don't really know the right
|
||||
-- switches (e.g.@: identifier character set) to be used
|
||||
-- to compile it.
|
||||
-- pragma Import because if we try to 'with' the unit and
|
||||
-- call it in Ada style, not only do we waste time recompiling it,
|
||||
-- but we don't know the right switches (e.g.@: identifier
|
||||
-- character set) to be used to compile it.
|
||||
|
||||
procedure Ada_Main_Program;
|
||||
pragma Import (Ada, Ada_Main_Program, "_ada_hello");
|
||||
@ -734,9 +732,9 @@ binder. We have added comments to more clearly indicate the function
|
||||
of each part of the generated ``Ada_Main`` package.
|
||||
|
||||
The code is standard Ada in all respects, and can be processed by any
|
||||
tools that handle Ada. In particular, it is possible to use the debugger
|
||||
tools that handle Ada. In particular, you can use the debugger
|
||||
in Ada mode to debug the generated ``Ada_Main`` package. For example,
|
||||
suppose that for reasons that you do not understand, your program is crashing
|
||||
suppose that for reasons you don't understand, your program is crashing
|
||||
during elaboration of the body of ``Ada.Text_IO``. To locate this bug,
|
||||
you can place a breakpoint on the call:
|
||||
|
||||
@ -745,5 +743,5 @@ you can place a breakpoint on the call:
|
||||
Ada.Text_Io'Elab_Body;
|
||||
|
||||
and trace the elaboration routine for this package to find out where
|
||||
the problem might be (more usually of course you would be debugging
|
||||
the problem might be (more usually, of course, you would be debugging
|
||||
elaboration code in your own application).
|
||||
|
@ -22,57 +22,58 @@ For information on GNAT Studio please refer to the
|
||||
System Requirements
|
||||
===================
|
||||
|
||||
Even though any machine can run the GNAT toolset and GNAT Studio IDE, in order
|
||||
to get the best experience, we recommend using a machine with as many cores
|
||||
as possible since all individual compilations can run in parallel.
|
||||
Even though any machine can run the GNAT toolset and GNAT Studio IDE,
|
||||
to get the best experience we recommend using a machine with as many cores
|
||||
as possible, allowing individual compilations to run in parallel.
|
||||
A comfortable setup for a compiler server is a machine with 24 physical cores
|
||||
or more, with at least 48 GB of memory (2 GB per core).
|
||||
|
||||
For a desktop machine, a minimum of 4 cores is recommended (8 preferred),
|
||||
For a desktop machine, we recommend a minimum of 4 cores (8 is preferred),
|
||||
with at least 2GB per core (so 8 to 16GB).
|
||||
|
||||
In addition, for running and navigating sources in GNAT Studio smoothly, we
|
||||
recommend at least 1.5 GB plus 3 GB of RAM per 1 million source line of code.
|
||||
In other words, we recommend at least 3 GB for for 500K lines of code and
|
||||
In addition, for running and smoothly navigating sources in GNAT Studio, we
|
||||
recommend at least 1.5 GB, plus 3 GB of RAM per million source lines of code.
|
||||
So we recommend at least 3 GB for 500K lines of code and
|
||||
7.5 GB for 2 million lines of code.
|
||||
|
||||
Note that using local and fast drives will also make a difference in terms of
|
||||
build and link time. Network drives such as NFS, SMB, or worse, configuration
|
||||
management filesystems (such as ClearCase dynamic views) should be avoided as
|
||||
much as possible and will produce very degraded performance (typically 2 to 3
|
||||
times slower than on local fast drives). If such slow drives cannot be avoided
|
||||
for accessing the source code, then you should at least configure your project
|
||||
file so that the result of the compilation is stored on a drive local to the
|
||||
machine performing the run. This can be achieved by setting the ``Object_Dir``
|
||||
project file attribute.
|
||||
Using fast, local drives can make a significant difference in build
|
||||
and link times. You should avoid network drives such as NFS, SMB, or
|
||||
worse, configuration management filesystems (such as ClearCase dynamic
|
||||
views) as much as possible since these will produce very degraded
|
||||
performance (typically 2 to 3 times slower than on fast, local
|
||||
drives). If you cannot avoid using such slow drives for accessing
|
||||
source code, you should at least configure your project file so
|
||||
the result of the compilation is stored on a drive local to the
|
||||
machine performing the compilation. You can do this by setting the
|
||||
``Object_Dir`` project file attribute.
|
||||
|
||||
.. _Running_GNAT:
|
||||
|
||||
Running GNAT
|
||||
============
|
||||
|
||||
Three steps are needed to create an executable file from an Ada source
|
||||
file:
|
||||
You need to take three steps to create an executable file from an Ada
|
||||
source file:
|
||||
|
||||
* The source file(s) must be compiled.
|
||||
* The file(s) must be bound using the GNAT binder.
|
||||
* All appropriate object files must be linked to produce an executable.
|
||||
* You must compile the source file(s).
|
||||
* You must bind the file(s) using the GNAT binder.
|
||||
* You must link all appropriate object files to produce an executable.
|
||||
|
||||
All three steps are most commonly handled by using the ``gnatmake``
|
||||
utility program that, given the name of the main program, automatically
|
||||
performs the necessary compilation, binding and linking steps.
|
||||
You most commonly perform all three steps by using the ``gnatmake``
|
||||
utility program. You pass it the name of the main program and it automatically
|
||||
performs the necessary compilation, binding, and linking steps.
|
||||
|
||||
.. _Running_a_Simple_Ada_Program:
|
||||
|
||||
Running a Simple Ada Program
|
||||
============================
|
||||
|
||||
Any text editor may be used to prepare an Ada program.
|
||||
(If Emacs is used, the optional Ada mode may be helpful in laying out the
|
||||
You may use any text editor to prepare an Ada program.
|
||||
(If you use Emacs, an optional Ada mode may be helpful in laying out the
|
||||
program.)
|
||||
The program text is a normal text file. We will assume in our initial
|
||||
example that you have used your editor to prepare the following
|
||||
standard format text file:
|
||||
standard format text file named :file:`hello.adb`:
|
||||
|
||||
|
||||
.. code-block:: ada
|
||||
@ -83,21 +84,18 @@ standard format text file:
|
||||
Put_Line ("Hello WORLD!");
|
||||
end Hello;
|
||||
|
||||
This file should be named :file:`hello.adb`.
|
||||
With the normal default file naming conventions, GNAT requires
|
||||
that each file
|
||||
contain a single compilation unit whose file name is the
|
||||
unit name,
|
||||
with periods replaced by hyphens; the
|
||||
unit name with periods replaced by hyphens; the
|
||||
extension is :file:`ads` for a
|
||||
spec and :file:`adb` for a body.
|
||||
You can override this default file naming convention by use of the
|
||||
special pragma ``Source_File_Name`` (for further information please
|
||||
see :ref:`Using_Other_File_Names`).
|
||||
special pragma ``Source_File_Name`` (see :ref:`Using_Other_File_Names`).
|
||||
Alternatively, if you want to rename your files according to this default
|
||||
convention, which is probably more convenient if you will be using GNAT
|
||||
for all your compilations, then the ``gnatchop`` utility
|
||||
can be used to generate correctly-named source files
|
||||
for all your compilations, then you use can use the ``gnatchop`` utility
|
||||
to generate correctly-named source files
|
||||
(see :ref:`Renaming_Files_with_gnatchop`).
|
||||
|
||||
You can compile the program using the following command (``$`` is used
|
||||
@ -108,16 +106,16 @@ as the command prompt in the examples in this document):
|
||||
$ gcc -c hello.adb
|
||||
|
||||
|
||||
``gcc`` is the command used to run the compiler. This compiler is
|
||||
``gcc`` is the command used to run the compiler. It is
|
||||
capable of compiling programs in several languages, including Ada and
|
||||
C. It assumes that you have given it an Ada program if the file extension is
|
||||
either :file:`.ads` or :file:`.adb`, and it will then call
|
||||
C. It assumes you have given it an Ada program if the file extension is
|
||||
either :file:`.ads` or :file:`.adb`, in which case it will call
|
||||
the GNAT compiler to compile the specified file.
|
||||
|
||||
The :switch:`-c` switch is required. It tells ``gcc`` to only do a
|
||||
compilation. (For C programs, ``gcc`` can also do linking, but this
|
||||
capability is not used directly for Ada programs, so the :switch:`-c`
|
||||
switch must always be present.)
|
||||
capability is not used directly for Ada programs, so you must always
|
||||
specify the :switch:`-c`.)
|
||||
|
||||
This compile command generates a file
|
||||
:file:`hello.o`, which is the object
|
||||
@ -126,11 +124,11 @@ an 'Ada Library Information' file :file:`hello.ali`,
|
||||
which contains additional information used to check
|
||||
that an Ada program is consistent.
|
||||
|
||||
To build an executable file, use either ``gnatmake`` or gprbuild with
|
||||
the name of the main file: these tools are builders that will take care of
|
||||
To build an executable file, use either ``gnatmake`` or ``gprbuild`` with
|
||||
the name of the main file: these tools are builders that perform
|
||||
all the necessary build steps in the correct order.
|
||||
In particular, these builders automatically recompile any sources that have
|
||||
been modified since they were last compiled, or sources that depend
|
||||
been modified since they were last compiled, as well as sources that depend
|
||||
on such modified sources, so that 'version skew' is avoided.
|
||||
|
||||
.. index:: Version skew (avoided by ``gnatmake``)
|
||||
@ -139,7 +137,7 @@ on such modified sources, so that 'version skew' is avoided.
|
||||
|
||||
$ gnatmake hello.adb
|
||||
|
||||
The result is an executable program called :file:`hello`, which can be
|
||||
The result is an executable program called :file:`hello`, which you can
|
||||
run by entering:
|
||||
|
||||
.. code-block:: sh
|
||||
@ -160,8 +158,8 @@ appear in response to this command.
|
||||
Running a Program with Multiple Units
|
||||
=====================================
|
||||
|
||||
Consider a slightly more complicated example that has three files: a
|
||||
main program, and the spec and body of a package:
|
||||
Consider a slightly more complicated example with three files: a
|
||||
main program and the spec and body of a package:
|
||||
|
||||
|
||||
.. code-block:: ada
|
||||
@ -210,15 +208,15 @@ following three separate files:
|
||||
Note that there is no required order of compilation when using GNAT.
|
||||
In particular it is perfectly fine to compile the main program first.
|
||||
Also, it is not necessary to compile package specs in the case where
|
||||
there is an accompanying body; you only need to compile the body. If you want
|
||||
there is an accompanying body; you only need compile the body. If you want
|
||||
to submit these files to the compiler for semantic checking and not code
|
||||
generation, then use the :switch:`-gnatc` switch:
|
||||
generation, use the :switch:`-gnatc` switch:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ gcc -c greetings.ads -gnatc
|
||||
|
||||
Although the compilation can be done in separate steps, in practice it is
|
||||
Although you can do the compilation in separate steps, in practice it's
|
||||
almost always more convenient to use the ``gnatmake`` or ``gprbuild`` tools:
|
||||
|
||||
.. code-block:: sh
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -9,10 +9,10 @@ Inline Assembler
|
||||
.. index:: Inline Assembler
|
||||
|
||||
If you need to write low-level software that interacts directly
|
||||
with the hardware, Ada provides two ways to incorporate assembly
|
||||
with the hardware, Ada provides two ways for you to incorporate assembly
|
||||
language code into your program. First, you can import and invoke
|
||||
external routines written in assembly language, an Ada feature fully
|
||||
supported by GNAT. However, for small sections of code it may be simpler
|
||||
supported by GNAT. However, for small sections of code, it may be simpler
|
||||
or more efficient to include assembly language statements directly
|
||||
in your Ada source program, using the facilities of the implementation-defined
|
||||
package ``System.Machine_Code``, which incorporates the gcc
|
||||
@ -24,14 +24,14 @@ including the following:
|
||||
* Automatic usage of the proper calling conventions
|
||||
* Access to Ada constants and variables
|
||||
* Definition of intrinsic routines
|
||||
* Possibility of inlining a subprogram comprising assembler code
|
||||
* Possibility of inlining a subprogram consisting of assembler code
|
||||
* Code optimizer can take Inline Assembler code into account
|
||||
|
||||
This appendix presents a series of examples to show you how to use
|
||||
the Inline Assembler. Although it focuses on the Intel x86,
|
||||
the general approach applies also to other processors.
|
||||
It is assumed that you are familiar with Ada
|
||||
and with assembly language programming.
|
||||
It is assumed you are familiar with both Ada
|
||||
and assembly language programming.
|
||||
|
||||
.. _Basic_Assembler_Syntax:
|
||||
|
||||
@ -99,9 +99,9 @@ pre-processor) documentation for further information.
|
||||
A Simple Example of Inline Assembler
|
||||
====================================
|
||||
|
||||
The following example will generate a single assembly language statement,
|
||||
The following example generate a single assembly language statement,
|
||||
``nop``, which does nothing. Despite its lack of run-time effect,
|
||||
the example will be useful in illustrating the basics of
|
||||
the example is useful in illustrating the basics of
|
||||
the Inline Assembler facility.
|
||||
|
||||
.. code-block:: ada
|
||||
@ -114,18 +114,18 @@ the Inline Assembler facility.
|
||||
|
||||
``Asm`` is a procedure declared in package ``System.Machine_Code``;
|
||||
here it takes one parameter, a *template string* that must be a static
|
||||
expression and that will form the generated instruction.
|
||||
expression that produces the generated instruction.
|
||||
``Asm`` may be regarded as a compile-time procedure that parses
|
||||
the template string and additional parameters (none here),
|
||||
from which it generates a sequence of assembly language instructions.
|
||||
the template string and any additional parameters (none, in this case)
|
||||
and generates one or more assembly language instructions.
|
||||
|
||||
The examples in this chapter will illustrate several of the forms
|
||||
for invoking ``Asm``; a complete specification of the syntax
|
||||
is found in the ``Machine_Code_Insertions`` section of the
|
||||
:title:`GNAT Reference Manual`.
|
||||
|
||||
Under the standard GNAT conventions, the ``Nothing`` procedure
|
||||
should be in a file named :file:`nothing.adb`.
|
||||
Under the standard GNAT conventions, you should put the ``Nothing`` procedure
|
||||
in a file named :file:`nothing.adb`.
|
||||
You can build the executable in the usual way:
|
||||
|
||||
::
|
||||
@ -155,7 +155,7 @@ where the options are:
|
||||
do not add runtime checks
|
||||
|
||||
This gives a human-readable assembler version of the code. The resulting
|
||||
file will have the same name as the Ada source file, but with a ``.s``
|
||||
file has the same name as the Ada source file but with a ``.s``
|
||||
extension. In our example, the file :file:`nothing.s` has the following
|
||||
contents:
|
||||
|
||||
@ -183,8 +183,8 @@ can differ on different targets. For example, GNU/Linux uses '#APP' while
|
||||
on NT you will see '/APP'.
|
||||
|
||||
If you make a mistake in your assembler code (such as using the
|
||||
wrong size modifier, or using a wrong operand for the instruction) GNAT
|
||||
will report this error in a temporary file, which will be deleted when
|
||||
wrong size modifier or using a wrong operand for the instruction) GNAT
|
||||
will report this error in a temporary file, which is deleted when
|
||||
the compilation is finished. Generating an assembler file will help
|
||||
in such cases, since you can assemble this file separately using the
|
||||
``as`` assembler that comes with gcc.
|
||||
@ -197,7 +197,7 @@ Assembling the file using the command
|
||||
|
||||
will give you error messages whose lines correspond to the assembler
|
||||
input file, so you can easily find and correct any mistakes you made.
|
||||
If there are no errors, ``as`` will generate an object file
|
||||
If there are no errors, ``as`` generates an object file called
|
||||
:file:`nothing.out`.
|
||||
|
||||
|
||||
@ -227,10 +227,10 @@ statements.
|
||||
Put_Line ("Flags register:" & Flags'Img);
|
||||
end Get_Flags;
|
||||
|
||||
In order to have a nicely aligned assembly listing, we have separated
|
||||
multiple assembler statements in the Asm template string with linefeed
|
||||
(ASCII.LF) and horizontal tab (ASCII.HT) characters.
|
||||
The resulting section of the assembly output file is:
|
||||
We have separated multiple assembler statements in the Asm template
|
||||
string with linefeed (ASCII.LF) and horizontal tab (ASCII.HT)
|
||||
characters in order to have a nicely aligned assembly listing. The
|
||||
resulting section of the assembly output file is:
|
||||
|
||||
::
|
||||
|
||||
@ -269,20 +269,21 @@ In the generated assembly code, one of the percent signs will be stripped off.
|
||||
Names such as ``%0``, ``%1``, ``%2``, etc., denote input or output
|
||||
variables: operands you later define using ``Input`` or ``Output``
|
||||
parameters to ``Asm``.
|
||||
An output variable is illustrated in
|
||||
the third statement in the Asm template string:
|
||||
An output variable is shown in
|
||||
the third section of the Asm template string:
|
||||
|
||||
::
|
||||
|
||||
movl %%eax, %0
|
||||
|
||||
The intent is to store the contents of the eax register in a variable that can
|
||||
be accessed in Ada. Simply writing ``movl %%eax, Flags`` would not
|
||||
necessarily work, since the compiler might optimize by using a register
|
||||
to hold Flags, and the expansion of the ``movl`` instruction would not be
|
||||
aware of this optimization. The solution is not to store the result directly
|
||||
but rather to advise the compiler to choose the correct operand form;
|
||||
that is the purpose of the ``%0`` output variable.
|
||||
The intent of this section is to store the contents of the ``eax``
|
||||
register in a variable that can be accessed in Ada. Simply writing
|
||||
``movl %%eax, Flags`` would not necessarily work, since the compiler
|
||||
might optimize by using a register to hold ``Flags``, and the expansion of
|
||||
the ``movl`` instruction would not be aware of this optimization. The
|
||||
solution is not to store the result directly but rather to advise the
|
||||
compiler to choose the correct operand form; that is the purpose of
|
||||
the ``%0`` output variable.
|
||||
|
||||
Information about the output variable is supplied in the ``Outputs``
|
||||
parameter to ``Asm``:
|
||||
@ -292,14 +293,14 @@ parameter to ``Asm``:
|
||||
Outputs => Unsigned_32'Asm_Output ("=g", Flags));
|
||||
|
||||
The output is defined by the ``Asm_Output`` attribute of the target type;
|
||||
the general format is
|
||||
the general format is:
|
||||
|
||||
.. code-block:: ada
|
||||
|
||||
Type'Asm_Output (constraint_string, variable_name)
|
||||
|
||||
The constraint string directs the compiler how
|
||||
to store/access the associated variable. In the example
|
||||
to store/access the associated variable. In the example:
|
||||
|
||||
.. code-block:: ada
|
||||
|
||||
@ -316,14 +317,14 @@ the optimizer from keeping it in a register. In contrast,
|
||||
uses the ``"r"`` (register) constraint, telling the compiler to
|
||||
store the variable in a register.
|
||||
|
||||
If the constraint is preceded by the equal character '=', it tells
|
||||
the compiler that the variable will be used to store data into it.
|
||||
If you precede the constraint with the equal character ('='), it tells
|
||||
the compiler that the variable will have data stored into it.
|
||||
|
||||
In the ``Get_Flags`` example, we used the ``"g"`` (global) constraint,
|
||||
allowing the optimizer to choose whatever it deems best.
|
||||
allowing the optimizer to choose whatever operand it deems best.
|
||||
|
||||
There are a fairly large number of constraints, but the ones that are
|
||||
most useful (for the Intel x86 processor) are the following:
|
||||
most useful for the Intel x86 processor are the following:
|
||||
|
||||
====== ==========================================
|
||||
*=* output constraint
|
||||
@ -340,9 +341,9 @@ most useful (for the Intel x86 processor) are the following:
|
||||
*q* use one of eax, ebx, ecx, edx, esi or edi
|
||||
====== ==========================================
|
||||
|
||||
The full set of constraints is described in the gcc and ``as``
|
||||
documentation; note that it is possible to combine certain constraints
|
||||
in one constraint string.
|
||||
The full set of constraints is described in the ``gcc`` and ``as``
|
||||
documentation; note that you can combine certain constraints
|
||||
into one constraint string.
|
||||
|
||||
You specify the association of an output variable with an assembler operand
|
||||
through the :samp:`%{n}` notation, where *n* is a non-negative
|
||||
@ -356,9 +357,8 @@ integer. Thus in
|
||||
Outputs => Unsigned_32'Asm_Output ("=g", Flags));
|
||||
|
||||
|
||||
``%0`` will be replaced in the expanded code by the appropriate operand,
|
||||
whatever
|
||||
the compiler decided for the ``Flags`` variable.
|
||||
``%0`` is replaced in the expanded code by the appropriate operand,
|
||||
whatever the compiler chose for the ``Flags`` variable.
|
||||
|
||||
In general, you may have any number of output variables:
|
||||
|
||||
@ -381,8 +381,8 @@ For example:
|
||||
where ``Var_A``, ``Var_B``, and ``Var_C`` are variables
|
||||
in the Ada program.
|
||||
|
||||
As a variation on the ``Get_Flags`` example, we can use the constraints
|
||||
string to direct the compiler to store the eax register into the ``Flags``
|
||||
As a variation on the ``Get_Flags`` example, we can use the constraint
|
||||
string to direct the compiler to store the ``eax`` register into the ``Flags``
|
||||
variable, instead of including the store instruction explicitly in the
|
||||
``Asm`` template string:
|
||||
|
||||
@ -402,7 +402,7 @@ variable, instead of including the store instruction explicitly in the
|
||||
end Get_Flags_2;
|
||||
|
||||
The ``"a"`` constraint tells the compiler that the ``Flags``
|
||||
variable will come from the eax register. Here is the resulting code:
|
||||
variable will come from the ``eax`` register. Here is the resulting code:
|
||||
|
||||
::
|
||||
|
||||
@ -415,7 +415,7 @@ variable will come from the eax register. Here is the resulting code:
|
||||
The compiler generated the store of eax into Flags after
|
||||
expanding the assembler code.
|
||||
|
||||
Actually, there was no need to pop the flags into the eax register;
|
||||
In fact, there was no need to pop the flags into the ``eax`` register;
|
||||
more simply, we could just pop the flags directly into the program variable:
|
||||
|
||||
.. code-block:: ada
|
||||
@ -441,7 +441,7 @@ Input Variables in Inline Assembler
|
||||
|
||||
The example in this section illustrates how to specify the source operands
|
||||
for assembly language statements.
|
||||
The program simply increments its input value by 1:
|
||||
The procedure simply increments its input value by 1:
|
||||
|
||||
.. code-block:: ada
|
||||
|
||||
@ -469,27 +469,27 @@ The program simply increments its input value by 1:
|
||||
end Increment;
|
||||
|
||||
The ``Outputs`` parameter to ``Asm`` specifies
|
||||
that the result will be in the eax register and that it is to be stored
|
||||
that the result is in the ``eax`` register and that it is to be stored
|
||||
in the ``Result`` variable.
|
||||
|
||||
The ``Inputs`` parameter looks much like the ``Outputs`` parameter,
|
||||
but with an ``Asm_Input`` attribute.
|
||||
The ``"="`` constraint, indicating an output value, is not present.
|
||||
|
||||
You can have multiple input variables, in the same way that you can have more
|
||||
You can have multiple input variables in the same way you can have more
|
||||
than one output variable.
|
||||
|
||||
The parameter count (%0, %1) etc, still starts at the first output statement,
|
||||
and continues with the input statements.
|
||||
|
||||
Just as the ``Outputs`` parameter causes the register to be stored into the
|
||||
target variable after execution of the assembler statements, so does the
|
||||
``Inputs`` parameter cause its variable to be loaded into the register
|
||||
target variable after execution of the assembler statements, the
|
||||
``Inputs`` parameter causes its variable to be loaded into the register
|
||||
before execution of the assembler statements.
|
||||
|
||||
Thus the effect of the ``Asm`` invocation is:
|
||||
|
||||
* load the 32-bit value of ``Value`` into eax
|
||||
* load the 32-bit value of ``Value`` into ``eax``
|
||||
* execute the ``incl %eax`` instruction
|
||||
* store the contents of eax into the ``Result`` variable
|
||||
|
||||
@ -520,7 +520,7 @@ frame) can be significant, compared to the amount of code in the subprogram
|
||||
body. A solution is to apply Ada's ``Inline`` pragma to the subprogram,
|
||||
which directs the compiler to expand invocations of the subprogram at the
|
||||
point(s) of call, instead of setting up a stack frame for out-of-line calls.
|
||||
Here is the resulting program:
|
||||
Here's the resulting program:
|
||||
|
||||
.. code-block:: ada
|
||||
|
||||
@ -593,14 +593,14 @@ such as Ada is that the compiler needs to be aware of which registers are
|
||||
being used by the assembly code. In some cases, such as the earlier examples,
|
||||
the constraint string is sufficient to indicate register usage (e.g.,
|
||||
``"a"`` for
|
||||
the eax register). But more generally, the compiler needs an explicit
|
||||
the ``eax`` register). But, more generally, the compiler needs an explicit
|
||||
identification of the registers that are used by the Inline Assembly
|
||||
statements.
|
||||
|
||||
Using a register that the compiler doesn't know about
|
||||
could be a side effect of an instruction (like ``mull``
|
||||
storing its result in both eax and edx).
|
||||
It can also arise from explicit register usage in your
|
||||
could be a side effect of an instruction (like ``mull``, which
|
||||
stores its result into both ``eax`` and ``edx``).
|
||||
It can also arise from explicit register usage within your
|
||||
assembly code; for example:
|
||||
|
||||
.. code-block:: ada
|
||||
@ -611,10 +611,10 @@ assembly code; for example:
|
||||
Inputs => Unsigned_32'Asm_Input ("g", Var_In));
|
||||
|
||||
where the compiler (since it does not analyze the ``Asm`` template string)
|
||||
does not know you are using the ebx register.
|
||||
does not know you are using the ``ebx`` register.
|
||||
|
||||
In such cases you need to supply the ``Clobber`` parameter to ``Asm``,
|
||||
to identify the registers that will be used by your assembly code:
|
||||
to identify the registers used by your assembly code:
|
||||
|
||||
|
||||
.. code-block:: ada
|
||||
@ -626,9 +626,9 @@ to identify the registers that will be used by your assembly code:
|
||||
Clobber => "ebx");
|
||||
|
||||
The Clobber parameter is a static string expression specifying the
|
||||
register(s) you are using. Note that register names are *not* prefixed
|
||||
by a percent sign. Also, if more than one register is used then their names
|
||||
are separated by commas; e.g., ``"eax, ebx"``
|
||||
register(s) you are using. Note that register names are *not*
|
||||
prefixed by a percent sign. Also, if more than one register is used,
|
||||
you separate their names by commas; e.g., ``"eax, ebx"``
|
||||
|
||||
The ``Clobber`` parameter has several additional uses:
|
||||
|
||||
@ -648,7 +648,7 @@ unwanted effects. For example, when an ``Asm`` invocation with an input
|
||||
variable is inside a loop, the compiler might move the loading of the input
|
||||
variable outside the loop, regarding it as a one-time initialization.
|
||||
|
||||
If this effect is not desired, you can disable such optimizations by setting
|
||||
If you don't want this to happen, you can disable such optimizations by setting
|
||||
the ``Volatile`` parameter to ``True``; for example:
|
||||
|
||||
.. code-block:: ada
|
||||
@ -664,7 +664,7 @@ By default, ``Volatile`` is set to ``False`` unless there is no
|
||||
``Outputs`` parameter.
|
||||
|
||||
Although setting ``Volatile`` to ``True`` prevents unwanted
|
||||
optimizations, it will also disable other optimizations that might be
|
||||
optimizations, it also disables other optimizations that might be
|
||||
important for efficiency. In general, you should set ``Volatile``
|
||||
to ``True`` only if the compiler's optimizations have created
|
||||
problems.
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user