Version 1.2 of ais/ai-00245.txt

Unformatted version of ais/ai-00245.txt version 1.2
Other versions for file ais/ai-00245.txt

!standard 10.1.4 (07)          00-10-30 AI95-00245/01
!class confirmation 00-10-30
!status work item 00-10-30
!status received 00-10-30
!qualifier Clarification
!priority Low
!difficulty Medium
!subject Consistency of inlined calls
!summary
The implementation must insure that a partition containing inlined subprograms is consistent. It can do this by requiring recompilation of units, or via a automatic recompilation mechanism.
!question
Consider a package P that contains explicitly inlined subprograms, and a main subprogram Q that is compiled after P's body and calls such subprograms. P's body is later changed and recompiled without any subsequent user actions causing Q to be recompiled or Q's code to be regenerated.
May program Q be rejected at link time, or must the linker automatically regenerate Q's code to be consistent with the new version of P's body? (The program may be rejected.)
Apparently, the obsolete version of P's body is not needed in the program because there is no semantic dependence on it, see 10.2(4). And the permission to remove Q from the environment when P's body is recompiled, see 10.1.4(7), is simply a permission. There are rules to prevent multiple versions of a compilation unit in a program, see 10.1.4(5), but they don't seem to help here because they are based on semantic dependence, and they are compile-time rules.
!response
The implementation permission to remove Q from the environment is intended to handle this case. It allows the implementation to require the recompilation of Q; alternatively, the implementation can automatically recompile Q at link-time.
10.2(27) ensures that an inconsistent partition cannot be linked. That means that an implementation that neither removed Q from the environment nor automatically recompiled it would be incorrect.
!ACATS test
An L-Test could be created to check that a program such as the one described is consistent.
!appendix

From: Dan Eilers
Sent: Thursday, October 19, 2000 8:27 PM

!topic consistency of inlined calls
!reference RM95-10.1.4(5-7)
!reference RM95-10.1.1(24-26)
!reference RM95-10.2(4)
!reference AARM95-10.1.4(7.d)
!reference AARM95-10.1.4(10.a)
!from Dan Eilers
!discussion

Consider a package P that contains explicitly inlined subprograms,
and a main subprogram Q that is compiled after P's body and calls such
subprograms.  P's body is later changed and recompiled without any
subsequent user actions causing Q to be recompiled or Q's code to be
regenerated.

May program Q be rejected at link time, or must the linker automatically
regenerate Q's code to be consistent with the new version of P's body?

Apparently, the obsolete version of P's body is not needed in the program
because there is no semantic dependence on it, see 10.2(4).  And the
permission to remove Q from the environment when P's body is recompiled,
see 10.1.4(7), is simply a permission.  There are rules to prevent multiple
versions of a compilation unit in a program, see 10.1.4(5), but they don't
seem to help here because they are based on semantic dependence, and they
are compile-time rules.

The concept of automatic linktime regeneration of code is mentioned
twice in the AARM, see 10.1.4(7.d) regarding inlined subprograms without
an explicit pragma inline, and 10.1.4(10.a) regarding macro-expanded
generics, but never even as implementation advise in the RM as far as
I can tell.

Note that the index for "dependence semantic" is missing 10.1.4(5) and
10.2(4), and the index for pragma inline is missing 10.1.4(7).

****************************************************************

From: Tucker Taft
Sent: Thursday, October 19, 2000 10:33 PM

Program Q may be rejected at link time.  Subprogram Q need
not be implicitly recompiled, but rather it may be considered
to be out-of-date.  In contrast, instantiation bodies are
required to be implicitly recompiled in Ada 95.

> Apparently, the obsolete version of P's body is not needed in the program
> because there is no semantic dependence on it, see 10.2(4).  And the
> permission to remove Q from the environment when P's body is recompiled,
> see 10.1.4(7), is simply a permission.

This is the key permission.  This is intended to mean
that the implementation may force the user to take
an explicit action to get Q back into the
environment (i.e. explicitly recompile it).  In other
words, Q may be considered "out of date."

No such permission exists for generic instantiations if
the generic body is updated, so the instantiations must
remain in the environment, and the linker must not complain
that they have become out-of-date.  At least that was the intent.

> ... There are rules to prevent multiple
> versions of a compilation unit in a program, see 10.1.4(5), but they don't
> seem to help here because they are based on semantic dependence, and they
> are compile-time rules.
>
> The concept of automatic linktime regeneration of code is mentioned
> twice in the AARM, see 10.1.4(7.d) regarding inlined subprograms without
> an explicit pragma inline, and 10.1.4(10.a) regarding macro-expanded
> generics, but never even as implementation advise in the RM as far as
> I can tell.

Automatic linktime regeneration is required for implicit inlining
and macro-expanded generics, so no implementation advice is
necessary.  It is permitted, but not required for explicit inlining,
and the manual gives no advice either way for this case.

> Note that the index for "dependence semantic" is missing 10.1.4(5) and
> 10.2(4), and the index for pragma inline is missing 10.1.4(7).

****************************************************************

From: Dan Eilers
Sent: Friday, October 20, 2000 1:24 AM

Tuck wrote:
> >                                                              And the
> > permission to remove Q from the environment when P's body is recompiled,
> > see 10.1.4(7), is simply a permission.
>
> This is the key permission.  This is intended to mean
> that the implementation may force the user to take
> an explicit action to get Q back into the
> environment (i.e. explicitly recompile it).  In other
> words, Q may be considered "out of date."

I understood the environment to be a compile-time concept (see 10.1.4(1)),
rather than a link-time concept.

10.1.4(5) requires a unit to exist in the environment in order to
compile a unit that depends on it, but 10.2(27) has no corresponding
requirement for linking.

I assume that "consistency" in 10.2(27) is intended to have the
same meaning as in 10.1.4(5), based on semantic dependency,
which doesn't cover "out of date" inlines.

Note: the index entry for "consistency among compilation units"
should add 10.2(27).

In an implementation where units are never removed from the environment
as long as their source file still exists, could a program be rejected
at link time for "out of date" inlines.

****************************************************************

From: Tucker Taft
Sent: Friday, October 20, 2000 10:52 AM

Dan Eilers wrote:

> I understood the environment to be a compile-time concept (see 10.1.4(1)),
> rather than a link-time concept.

The environment is a compile-time, link-time, and run-time
concept (see 10.1.4(1), 10.2(13), and 10.2(25)).

> 10.1.4(5) requires a unit to exist in the environment in order to
> compile a unit that depends on it, but 10.2(27) has no corresponding
> requirement for linking.
>
> I assume that "consistency" in 10.2(27) is intended to have the
> same meaning as in 10.1.4(5), based on semantic dependency,
> which doesn't cover "out of date" inlines.

Out of date inlines is a concept that doesn't exist in
the manual.  Inlining is supposed to be semantically
neutral, except for certain subtleties having to do
with 11.6 "independence", so clearly an inlined call
must be based on the same body as any out-of-line call.

The "consistency" of 10.2(27) is intended to require that
no two versions of the same unit will exist in the partition.
The semantics of executing the partition are determined by
the source code for the units included in the partition;
whether or not the source is translated into some other form
(e.g. machine code) is irrelevant to this, as is it irrelevant
whether or not inline expansion is occurring (modulo 11.6).

> Note: the index entry for "consistency among compilation units"
> should add 10.2(27).

Good point.

> In an implementation where units are never removed from the environment
> as long as their source file still exists, could a program be rejected
> at link time for "out of date" inlines.

From a legalistic point of view, the manual actually doesn't
say anything about what are the full prerequisites to linking,
since the whole process of building a partition is
implementation defined.  I think the intent was that the
rules for compilation would apply to linking, in particular
that if something is still "in" the environment with respect
to compilation, it should be considered "in" the environment
with respect to linking.  However, now that I look through
10.2, I don't really see anything explicit to that effect,
so I suppose your linker could be as "unfriendly" as you
want it to be.  From a practical point of view, the ACATS
tests have generally made the interpretation suggested above,
and presumably vendors have lived with it, and probably users
have grown accustomed to the availability of a semi-automatic
linking process.

I think the key legalistic requirement is that *if*
a unit gets included in an environment, then its semantics
must be based on a single version of its source code and
a single, consistent version of the source code
of the other units.  Whether the user has to take
explicit actions before linking is not really specified
by 10.2.  By contrast, 10.1.4 seems clearer that no
explicit actions are required before compiling in certain
cases, such as a change to a generic body or an implicitly
inlined body.

****************************************************************

From: Robert Dewar
Sent: Friday, October 20, 2000 11:02 AM

<<May program Q be rejected at link time, or must the linker automatically
regenerate Q's code to be consistent with the new version of P's body?>>

Of course the answer is yes, it can be rejected, there is never a requirement
for the linker to do "compilation" in this sense.

****************************************************************

From: Dan Eilers
Sent: Saturday, October 21, 2000 12:28 PM

If there is never a requirement for the linker to do automatic "compilation"
to fix up "out-of-date" explicit inlines, is there a requirement for the
linker to do automatic "compilation" to fix up "out-of-date" units where
the compiler acted "as if" there was an explicit inline on a unit that
it noticed contained lots of very small subprograms?  This seems to be
required by AARM 10.1.4(7.d), but perhaps that should just be considered
implementation advise and not be tested by ACATS.

****************************************************************

From: Robert Dewar
Sent: Saturday, October 21, 2000 7:14 PM

<<If there is never a requirement for the linker to do automatic "compilation"
to fix up "out-of-date" explicit inlines, is there a requirement for the
linker to do automatic "compilation" to fix up "out-of-date" units where
the compiler acted "as if" there was an explicit inline on a unit that
it noticed contained lots of very small subprograms?  This seems to be
required by AARM 10.1.4(7.d), but perhaps that should just be considered
implementation advise and not be tested by ACATS.>>

Obviously if a compiler does something in "as-if" mode then it must do
whatever is necessary to ensure that the behavior really is "as-if".

****************************************************************

From: Dan Eilers
Sent: Monday, October 23, 2000 3:38 AM

I take that to mean no, there is no requirement for the linker to do
automatic "compilation" for either explicit inlines or properly
implemented implicit inlines, and so AARM 10.1.4(7.d) should not
be tested by ACATS.  Did I understand correctly?  If so, I hope
that AARM 10.1.4(10.a) should also not be tested for the same reason.

****************************************************************

From: Randy Brukardt
Sent: Monday, October 30, 2000 10:10 PM

Dan said:

> Note that the index for "dependence semantic" is missing 10.1.4(5) and
> 10.2(4), and the index for pragma inline is missing 10.1.4(7).

Based on my understanding of the RM's index, I don't think these would be
justified.
As I understand the index, it indexes only places where things are
*defined*, not where they are *used*. These are all *uses*. (Whether that is
a good idea is another issue altogether, but I think it is important to keep
the index consistent.)

****************************************************************

From: Randy Brukardt
Sent: Monday, October 30, 2000 10:28 PM

> I take that to mean no, there is no requirement for the linker to do
> automatic "compilation" for either explicit inlines or properly
> implemented implicit inlines, and so AARM 10.1.4(7.d) should not
> be tested by ACATS.  Did I understand correctly?  If so, I hope
> that AARM 10.1.4(10.a) should also not be tested for the same reason.

I don't think Robert meant to imply that. I thought he meant that implicit
inlines ought to behave "as-if" there is no inline at all.

Certainly, *I* think that implicit inlines should be exactly that, and if
that means that you have to do link-time compilation, so be it. (If you
don't like that, don't implement implicit inlining!!!)

OTOH, I don't think it would ever be possible for AARM 10.1.4(7.d) to be
explicitly tested by an ACATS test: how could you possibly insure that a
unit had an implicit inline? But certainly, your interpretation would allow
an implementation to reject linking of any ACATS test that tried to replace
a unit with a new body after compiling another unit containing a call to a
subprogram in the first unit (because you could always claim that the
subprogram had been implicitly inlined). That would be madness.

So, whether or not 10.1.4(7.d) is tested, it is still true. And it has no
bearing on whether 10.1.4(10.a) should be tested, given that there is a
Defect Report (8652/0108) confirming  10.1.4(10-10.a). Indeed, there is
already a test requiring this behavior. (I converted the test to a 'C' test
after an implementor complained that the test was misclassified as an 'L'
test.)

****************************************************************

From: Robert Dewar
Sent: Tuesday, October 31, 2000 7:18 AM

<<I don't think Robert meant to imply that. I thought he meant that implicit
inlines ought to behave "as-if" there is no inline at all.

Certainly, *I* think that implicit inlines should be exactly that, and if
that means that you have to do link-time compilation, so be it. (If you
don't like that, don't implement implicit inlining!!!)>>

Yes, of course that's what I meant, if you do anything like this implicitly,
it needs to stay implicit :-)

****************************************************************

From: Dan Eilers
Sent: Wednesday, November 01, 2000 8:58 PM

Randy wrote:
> Certainly, *I* think that implicit inlines should be exactly that, and if
> that means that you have to do link-time compilation, so be it. (If you
> don't like that, don't implement implicit inlining!!!)

Our implementation implements implicit inlines "as if" there was
an explicit inline in the source code, taking advantage of the
permission to remove units with out-of-date inlined code from the
library.

Are you saying our implementation violates the standard?

> So, whether or not 10.1.4(7.d) is tested, it is still true. And it has no
> bearing on whether 10.1.4(10.a) should be tested, given that there is a
> Defect Report (8652/0108) confirming  10.1.4(10-10.a). Indeed, there is
> already a test requiring this behavior. (I converted the test to a 'C' test
> after an implementor complained that the test was misclassified as an 'L'
> test.)

I am familiar with Defect Report 8652/0108, and quite sure that it
does not confirm or even mention AARM 10.1.4(10-10.a).  8652/0108 is a
compile-time issue, (requiring the compiler not to reject a unit that
depends on an incomplete generic unit).  10.1.4(10-10.a) is non-normative
link-time advise regarding the commands for invoking the linker.
Your C test for AARM 10.1.4(10-10.a) is invalid as a test for 8652/0108.
A proper test for 8652/0108 would be a B test checking that no error
was generated.

****************************************************************

From: Dan Eilers
Sent: Wednesday, November 01, 2000 8:33 PM

Randy wrote:
> As I understand the index, it indexes only places where things are
> *defined*, not where they are *used*.

This is a misunderstanding.

****************************************************************

From: Robert Dewar
Sent: Wednesday, November 01, 2000 10:05 PM

<<Our implementation implements implicit inlines "as if" there was
an explicit inline in the source code, taking advantage of the
permission to remove units with out-of-date inlined code from the
library.

Are you saying our implementation violates the standard?>>

Yes, I consider this non-compliant

****************************************************************

From: Dan Eilers
Sent: Thursday, November 02, 2000 2:52 AM

Robert wrote:
> <<Our implementation implements implicit inlines "as if" there was
> an explicit inline in the source code, taking advantage of the
> permission to remove units with out-of-date inlined code from the
> library.
>
> Are you saying our implementation violates the standard?>>
>
> Yes, I consider this non-compliant

If true, surely this is an unintentional difference from Ada83
that should be fixed.

****************************************************************

From: Robert Dewar
Sent: Thursday, November 02, 2000 6:59 AM

<<If true, surely this is an unintentional difference from Ada83
that should be fixed.>>

No, I think this would be a non-compliance in Ada 83 as well.

If you allow arbitrary obsoleting of this kind, then an implementation
can do all kinds of horrible things, and indeed you can easily create
a situation where it is impossible to build some programs.

****************************************************************

From: Randy Brukardt
Sent: Thursday, November 02, 2000 2:07 PM

> <<If true, surely this is an unintentional difference from Ada83
> that should be fixed.>>
>
> No, I think this would be a non-compliance in Ada 83 as well.
>
> If you allow arbitrary obsoleting of this kind, then an implementation
> can do all kinds of horrible things, and indeed you can easily create
> a situation where it is impossible to build some programs.

Right. But keep in mind this only applies to the standard (ACATS compliant)
mode. Certainly an implementation can have a mode that does something else
useful for their customers (as per 1.1.5(11)).

****************************************************************

From: Robert Dewar
Sent: Thursday, November 02, 2000 8:04 PM

A compiler can do anything it likes in non-standard mode, including for
example compiling C++ instead of Ada :-)

****************************************************************

From: Robert Dewar
Sent: Thursday, November 02, 2000 10:12 AM
To: ADA-COMMENT@ACM.ORG; ada-comment@ada-auth.org
Subject: Re: [Ada-Comment] consistency of inlined calls

<<If you allow arbitrary obsoleting of this kind, then an implementation
can do all kinds of horrible things, and indeed you can easily create
a situation where it is impossible to build some programs.
>>

Note that this is only a problem if it is visible, or more accurately if
there is no way to make it transparent.

For example, with GNAT, our "official" 100% RM-compliant compilation model
looks like this:

1. Compilation is done by first using gnatchop (to deal with compilations
and also with compiling configuration pragmas on their own), followed
by compilations using gcc -c -gnatC, which diagnoses all illegalities
and inserts the unit into the compilation environment (i.e. the ALI file).

2. Binding is done using gnatmake, which also happens to perform some
code generation activity :-) Of course the RM has nothing to say about
whether "code generation" (whatever that is, the term is not comprehensible
in formal RM terms) takes place at "compile" time or "link" time.

As long as implicit inlining and its necessary recompilations are hidden
under the covers in a similar manner, then of course there is no issue
of non-conformance with the compilation model in the RM.

****************************************************************

From: Erhard Ploedereder
Sent: Thursday, November 02, 2000 9:11 AM

This issue (of dependents of generic units or of inline-caused dependencies)
has been gone over for Ada87, by the 95 DRs and many others.

In the end, the only consensus that was able to be achieved is one that
no program shall reach execution with an inconsistent set of compilation
units as the basis for the executed code.  This is the AXIOM, basically
stated in Note 10.1.4(8), to which the rules of the language are geared.

And yes, implicit recompilation for implicit inlines and implicit
recompilation of dependents of a generic, whose body has changed, are
the most user-friendly behavior. The words in the manual indicate that
intent.

But, because of the many implementation-defined aspects of the
compilation process, there are enough loopholes that other
compile-time behavior can be equally argued to be "conforming", as long
as the AXIOM is preserved.

Explicitly mentioning all the possible compiler behaviors in 10.1.4(7)
would really be counterproductive. In that sense DR108 is right in saying
"10.1.4(7) is intended to be complete". The next sentence in DR108
acknowledges the leeway that implementations have anyway. In a way,
10.1.4(7) cannot be complete, ever, with so much implementation-dependence
involved.

What made this liberal implementation-definedness acceptable to the vast
majority (including the then ACVC95-writers) is the fact that these issues
have no way of endangering portability of Ada software, which is the main
objective of having a rigorous language standard and conformance
enforcement.

****************************************************************

From: Dan Eilers
Sent: Thursday, November 02, 2000 6:54 PM

Randy wrote:
> > <<If true, surely this is an unintentional difference from Ada83
> > that should be fixed.>>
> >
> > No, I think this would be a non-compliance in Ada 83 as well.
> >
> > If you allow arbitrary obsoleting of this kind, then an implementation
> > can do all kinds of horrible things, and indeed you can easily create
> > a situation where it is impossible to build some programs.
>
> Right. But keep in mind this only applies to the standard (ACATS compliant)
> mode. Certainly an implementation can have a mode that does something else
> useful for their customers (as per 1.1.5(11)).

We do "as if" inlining in our standard mode.
As Erhard notes, it is user friendly to have a way to do
automatic recompilations.  We of course have an "ada make"
tool that will do such automatic recompilations, but we
don't invoke this tool during validations, either as
part of the compiler or as part of the linker.  Nor do
we believe it is reasonable or necessary to do so.

****************************************************************

From: Randy Brukardt
Sent: Thursday, November 02, 2000 8:17 PM

Do you pass all of the ACATS tests that way? If so, no problem (even if it
might be technically non-conforming). Otherwise, it is "necessary"
("reasonable" is just an opinion). (Of course, you could raise a dispute
against particular tests -- I'll be happy to run those through the dispute
process.)

****************************************************************


Questions? Ask the ACAA Technical Agent