[comp.lang.ada] Dynamic Address Clauses??

LINNIG@eg.csc.ti.COM (Mike Linnig) (06/01/88)

Folks,

The following package was compiled with two compilers (DEC Ada and
Tartan 1750a Ada).  Both allowed the declaration of X.  DEC ada
complained about the type conversion used for the rep clause
in ANOTHER.


Assuming one or both is legal, what do they mean???

	Mike Linnig,
	Texase Instruments



------------------------------------------------------------
with SYSTEM;
use SYSTEM;
package DYNAMIC_ADDR is
  subtype STUPID is SYSTEM.ADDRESS;

  function DYNAMIC return STUPID;  -- just some function


  X: INTEGER;
  for X use at DYNAMIC;  -- just what does this mean??


  ANOTHER: INTEGER;
  for ANOTHER USE AT stupid(x); 
                -- I guess we can use x as a pointer
                -- but is it only evaluated at package elaboration?

end DYNAMIC_ADDR;

firth@sei.cmu.edu (Robert Firth) (06/02/88)

In article <8806011944.AA06549@ti.com> LINNIG@eg.csc.ti.COM (Mike Linnig) writes:
>Folks,
>
>The following package was compiled with two compilers (DEC Ada and
>Tartan 1750a Ada).  Both allowed the declaration of X.  DEC ada
>complained about the type conversion used for the rep clause
>in ANOTHER.

>Assuming one or both is legal, what do they mean???

Wow!  Yes, both address clauses are legal according to the RM [13.5],
which requires a "simple expression" yielding a value of type ADDRESS.
Note particularly that the RM does NOT require a static expression!

However, the second simple expression - stupid(x) - is not portable.
It assumes that INTEGER and ADDRESS are interconvertible, which will
be so only if ADDRESS is a numeric type.  Evidently it is on the one
machine and not on the other.

Finally, there is a problem here - there is a reference to the
value in X when X in fact has no value.  The program is therefore
"erroneous", by RM [3.2.1 (17,18)]

And what does it "mean"?  I've commented the code to show what I think
it means.

------------------------------------------------------------
with SYSTEM;
use SYSTEM;
package DYNAMIC_ADDR is
  subtype STUPID is SYSTEM.ADDRESS;

  function DYNAMIC return STUPID;  -- just some function
  X: INTEGER;
  for X use at DYNAMIC;  -- just what does this mean??
		-- [RF] call the function DYNAMIC.  The return value
		--      is the address of X.  The implementation will
		--	probably declare a hidden pointer and then
		--	reference X indirectly through it

  ANOTHER: INTEGER;
  for ANOTHER USE AT stupid(x); 
		-- [RF] similarly, fetch the value of X (NOT its address)
		--	convert that value to an address, and put ANOTHER
		--	there.  Again, this probably means building a
		--	hidden pointer

                -- I guess we can use x as a pointer
                -- but is it only evaluated at package elaboration?

	-- [RF] the code I'd expect to see:
	--	declare space for 2 pointers (REFX and REFANOTHER)
	--	call DYNAMIC
	--	store return value in REFX
	--	fetch value of X (ie load indirect through REFX)
	--	store that value in REFANOTHER

end DYNAMIC_ADDR;

rfg@nsc.nsc.com (Ron Guilmette) (06/03/88)

In article <8806011944.AA06549@ti.com> LINNIG@eg.csc.ti.COM (Mike Linnig) writes:

>The following package was compiled with two compilers (DEC Ada and
>Tartan 1750a Ada).  Both allowed the declaration of X.  DEC ada
>complained about the type conversion used for the rep clause
>in ANOTHER.
>Assuming one or both is legal, what do they mean???
>

>  X: INTEGER;
>  for X use at DYNAMIC;  -- just what does this mean??

I have at least a fuzzy (but not warm) feeling as to the meaning of the code
shown above, however a very similar construction has disturbed me deeply,
to wit:

	procedure P;
	for P use at DYNAMIC;

For a true embedded system, I can understand that one may want to fix certain
routines at certain places via:

	procedure P;
	for P use at STATIC;

However I cannot envision any case in which dynamic relocation of routines
WHILE THE PROGRAM IS RUNNING would be of any benefit.  I can however
predict that such a capability might be an implementor's nightmare.
Note that 13.5(5) seem to allow (and now perhaps require?) such a
capability in all implementations!  Wow!
-- 
// Ron Guilmette		//  C++ is nice,
-- National SemiConductor	--  Ada keeps my wallet happy,
?? rfg@nsc.nsc.com		??  but there has got to be something better...

markb@sdcrdcf.UUCP (06/03/88)

In article <5140@nsc.nsc.com> rfg@nsc.UUCP (Ron Guilmette) writes:
<... however a very similar construction has disturbed me deeply,
<to wit:
<       procedure P;
<       for P use at DYNAMIC;
<For a true embedded system, I can understand that one may want to fix certain
<routines at certain places via:
<       procedure P;
<       for P use at STATIC;
<However I cannot envision any case in which dynamic relocation of routines
<WHILE THE PROGRAM IS RUNNING would be of any benefit.  I can however
<predict that such a capability might be an implementor's nightmare.
<Note that 13.5(5) seem to allow (and now perhaps require?) such a
<capability in all implementations!  Wow!

A good reason to allow this is multic-like dymanic procedure linking.
A side effect of the routine DYMANIC may be to load the code you wish
to run via the name P into memory and then return its address.

Mark Biggar
{allegra,burdvax,cbosgd,hplabs,ihnp4,akgua,sdcsvax}!sdcrdcf!markb
markb@rdcf.sm.unisys.com

daveb@geac.UUCP (David Collier-Brown) (06/06/88)

| In article <8806011944.AA06549@ti.com> LINNIG@eg.csc.ti.COM (Mike Linnig) writes:
| ...
| X: INTEGER;
| for X use at DYNAMIC;  -- just what does this mean??

In article <5140@nsc.nsc.com> rfg@nsc.UUCP (Ron Guilmette) writes:
| I have at least a fuzzy (but not warm) feeling as to the meaning of the code
| shown above, however a very similar construction has disturbed me deeply,
| to wit:
| 
| 	procedure P;
| 	for P use at DYNAMIC;
| 
| For a true embedded system, I can understand that one may want to fix certain
| routines at certain places via:
| 
| 	procedure P;
| 	for P use at STATIC;
| 
| However I cannot envision any case in which dynamic relocation of routines
| WHILE THE PROGRAM IS RUNNING would be of any benefit.  I can however
| predict that such a capability might be an implementor's nightmare.

  Well, I can suggest two cases where relocation of routines which
is transparent to the program may be of use:
	1) shared libraries
	2) replacement chipsets
  Both are really variants of the same thing, a piece of code which
may be replaced at run-time, either because its at a different
address than it was at link-time, or because it had to be replaced
due to an error.

  I'm personally attracted to the replacement-of-chips argument,
since one might want to replace one of a large number of ROM chips
in the field.  And not replace the whole set or board.

  In a non-embedded system, dynamic replacement is a long-term
maintenance win, as the Multicians found many moons ago.

--dave (Ichbiah was a Multician) c-b

ps: This is notably better than the procedure-pointer quasi-kludge
    of PL/1, B and C.
-- 
 David Collier-Brown.  {mnetor yunexus utgpu}!geac!daveb
 Geac Computers Ltd.,  | "His Majesty made you a major 
 350 Steelcase Road,   |  because he believed you would 
 Markham, Ontario.     |  know when not to obey his orders"

rfg@nsc.nsc.com (Ron Guilmette) (06/09/88)

Regarding the use of:

	procedure P;
	for P use at DYNAMIC;

In article <2817@geac.UUCP> daveb@geac.UUCP (David Collier-Brown) writes:
>
>  Well, I can suggest two cases where relocation of routines which
>is transparent to the program may be of use:
>	1) shared libraries
>	2) replacement chipsets
>  Both are really variants of the same thing, a piece of code which
>may be replaced at run-time, either because its at a different
>address than it was at link-time, or because it had to be replaced
>due to an error.

I'm sorry, but I have to say that the above statements don't really address
my initial concerns.

First, note that the EXPLICIT use of the address clause implies very clearly
that whatever is happening is not "transparent" to the user's program, but
rather that the program must actively participate in defining (or using)
the "effects" which are to occur.

Second, I believe that my original posting asked why it would ever be of
any value to use a dynamic address clause for a procedure.  Just saying
that the procedure is at a different address than it was at link time
begs the question.  Why is it at a different address?  Under what circum-
stances whould it be useful for the procedure to be "at" a different
(program-specified) address?

I don't think that shared-libraries are a case worth considering because
any reasonable linker should know about such things and should, in fact,
make their usage truly transparent to the program.

The possibility of using dynamic procedure address clauses to simply route
calls around defective and or outdated RAM/ROM versions of the procedures
involved sounds like a plausable use for this language "feature", however
such usage conflicts directly with my initial assumptions regarding the
intended semantics of dynamic address clauses for procedures.

The question I would now like to pose to the comp.lang.ada readers is this:
"Should a dynamic address clause for a procedure be considered to be simply
a DECLARATIVE statement (i.e. the procedure ALREADY resides here) or should
it be considered to be an EXECUTABLE statement (i.e. PUT the procedure code
at this location, regardless of where it currently resides)?"

I have been assuming the latter interpretation.  What do y'all think?

stt@ada-uts (06/10/88)

I have always presumed address clauses were directives to
the compiler or the linker, but certainly not to the run-time system.

The interpretation of the specified address is implementation-dependent,
including whether it is accepted.  The fact that
simple_expression is allowed rather than simply a literal
is simply to allow some freedom to the implementation, but
in no way requires that dynamic address clauses be supported.

As a compiler implementor one certainly has the freedom to
define address clauses as one sees fit, but if this discussion
is aimed at gaining a consensus as to the "normal" or "standard"
interpretation of address clauses, I would expect them to be
limited to expressions which can be evaluated at or before link-time.

For example, one might allow the sum of the address of one
unit and an offset for the address of a second unit.

To me it seems kind of pointless to try and figure out a meaning
for an address expression which will probably never be accepted by
an Ada compiler.

S. Tucker Taft
Intermetrics, Inc.
Cambridge, MA  02138

jmoody@DCA-EMS.ARPA (Jim Moody, DCA C342) (06/10/88)

Ron Guilmette writes:

'Regarding the use of:

procedure P;
for P use at DYNAMIC;

First, note that the EXPLICIT use of the address clause implies very clearly
that whatever is happening is not "transparent" to the user's program, but
rather that the program must actively participate in defining (or using)
the "effects" which are to occur.

. . .

The question I would now like to pose to the comp.lang.ada readers is this:
"Should a dynamic address clause for a procedure be considered to be simply
a DECLARATIVE statement (i.e. the procedure ALREADY resides here) or should
it be considered to be an EXECUTABLE statement (i.e. PUT the procedure code
at this location, regardless of where it currently resides)?"

I have been assuming the latter interpretation.  What do y'all think?'

We have to distinguish two cases.  The first is what, I think, everyone else     
who has been writing about this problem is assuming.  Let me put the code        
fragment in a full setting.

With System;
Package ExternalRelocatedProcedure is

Procedure P(A: in out ArgumentType);

Private

Function Dynamic return System.Address;
Pragma Interface (Assembler, Dynamic);
Pragma Interface (Assembler, P);
For P use at Dynamic;

End ExternalRelocatedProcedure;

In this case, the rep spec is purely declarative.  It tells the compiler that    
there is some procedure which can be called, how to call it and how to find out  
where it will be at run time.  This is presumably how replacement chip sets      
would be handled.  Note that the user of P does not explicitly use the rep       
spec, the implementer of P does.

The second and more problematical case is the one that Ron Guilmette is          
concerned about.  This is the case where a subprogram body is given together     
with an address clause, thus:

Procedure P is
  X,Y : SomeVariableType;
begin
  DoSomething;
  DoSomethingMore;
end P;
For P use at Dynamic;

It is not at all clear to me what this case requires of the implementation.  I   
cannot envisage how such a declaration might be used, but that may simply be my  
failure.  My best guess is the following.  13.5(5) requires that Dynamic be      
"the address required for the machine code associated with the body of" P,       
which begs a lot of questions.  There is nothing in the LRM which requires       
implementations to generate compact code for a subprogram body.  An              
implementation is, I assume, free to disperse a subprogram body all over         
memory, an instruction followed by a jump to an instruction followed by a jump   
to an instruction . . . .  That this is an unlikely implementation is agreed,    
but what its possibility implies is that the address clause does not require     
relocation of the machine code associated with the body of P.  It is enough, I   
think, that the implementation place, at the address returned by Dynamic, a      
jump to the beginning of the machine code associated with the body of P.  This   
makes it an executable statement (not a purely declarative one), but its         
execution asks a lot less of the implementation than Ron Guilmette assumed.

hyland@esosun.UUCP (Steve Hyland) (06/11/88)

In article <5151@nsc.nsc.com> rfg@nsc.UUCP (Ron Guilmette) writes:
>Regarding the use of:
>

>	for P use at DYNAMIC;
>

>any value to use a dynamic address clause for a procedure.  Just saying
>that the procedure is at a different address than it was at link time
>begs the question.  Why is it at a different address?  Under what circum-
>stances whould it be useful for the procedure to be "at" a different
>(program-specified) address?
>

Actually, I can think of an additional usage for this.

In my X Toolkit, I will allow the programmer the flexibility of
associating specific procedures, "Call Backs", to be executed whenever
a toolkit widget such as a scroll bar is moved. The compiler will
handle the association between the call back and the widget.

However, there are situations where application USERS may wish to change
these association dynamically, say by causing a different call back to
be executed when the scroll bar is moved. Dynamic address clauses would
allow me to associate a different call back in this way. 

I won't argue whether this is considered good or bad programming. Something
this flexible should be used, albeit carefully.

Steve Hyland

daveb@geac.UUCP (David Collier-Brown) (06/15/88)

Regarding the use of:

	procedure P;
	for P use at DYNAMIC;

In article <2817@geac.UUCP> daveb@geac.UUCP (David Collier-Brown) writes:
|| 
||   Well, I can suggest two cases where relocation of procedures which
|| is transparent to the program may be of use:
      ^^^^^^^^^^^

In article <5151@nsc.nsc.com> rfg@nsc.UUCP (Ron Guilmette) writes:
| First, note that the EXPLICIT use of the address clause implies very clearly
| that whatever is happening is not "transparent" to the user's program, but
| rather that the program must actively participate in defining (or using)
| the "effects" which are to occur.

  OOPS!  I used "transparent" ambiguously.
  What I really meant was that the the address to use is marked as
unusual only at one place, and that the **programmer** can regard
its relocation as occurring transparently at runtime.
  This is in contrast to "C", where relocation is done explicitly
and obviously at every reference to or call to the procedure:
	int	(*the_fcn_pointer)();
	...

	the_fcn_pointer = dynamic();
	...
	i = (*the_fcn_pointer)(is,somewhat,visible);

  What I should have said is that it meets modern maintainability
standards, not that it was transparent (save in a trivial sense).


| The question I would now like to pose to the comp.lang.ada readers is this:
| "Should a dynamic address clause for a procedure be considered to be simply
| a DECLARATIVE statement (i.e. the procedure ALREADY resides here) or should
| it be considered to be an EXECUTABLE statement (i.e. PUT the procedure code
| at this location, regardless of where it currently resides)?"

| I have been assuming the latter interpretation.  What do y'all think?

  If it was a simple variable, what would the "use at" clause mean?
Should this be the same for a procedure?  I **think** its
declarative...

 --dave
-- 
 David Collier-Brown.  {mnetor yunexus utgpu}!geac!daveb
 Geac Computers Ltd.,  | "His Majesty made you a major 
 350 Steelcase Road,   |  because he believed you would 
 Markham, Ontario.     |  know when not to obey his orders"

bseymour@potpourri.UUCP (Burch Seymour) (06/15/88)

in article <8806011944.AA06549@ti.com>, LINNIG@eg.csc.ti.COM (Mike Linnig) says:

> with SYSTEM;
> use SYSTEM;
> package DYNAMIC_ADDR is
>   subtype STUPID is SYSTEM.ADDRESS;
> 
>   function DYNAMIC return STUPID;  -- just some function
> 
>   X: INTEGER;
>   for X use at DYNAMIC;  -- just what does this mean??

What this does on our compiler (Telesoft Telegen II - Gould version) is
call function DYNAMIC and store the returned value into X. This is done
during the elaboration of the specification of package DYNAMIC_ADDR.
Later references to X do not call the function, just use the current
value of X.

>   ANOTHER: INTEGER;
>   for ANOTHER USE AT stupid(x); 
> -- this compiles on one compiler and gets illegal conversion type
> -- on another one. Why?

According to type conversion rules (see LRM section 4.6.8), the operand
and target types must be related. The type system.address is
implementation specific (LRM 13.7). Some compilers just derive
system.address from integer. In this case you can convert integer to
address without using unchecked conversion since they have the same
base type. On others this is not true and the conversion is illegal.
That's why this works on some compilers and not on others.

-Burch Seymour- Gould CSD  Ft Lauderdale, Fla
=====================================================================

rfg@nsc.nsc.com (Ron Guilmette) (06/16/88)

In article <57900075@ada-uts> stt@ada-uts writes:
>
>To me it seems kind of pointless to try and figure out a meaning
>for an address expression which will probably never be accepted by
>an Ada compiler.

Granted, but it is my understanding that the new rules of the Ada implementa-
tion game require the implementation of all of Chapter 13, unless the
implementor can show (I guess to the AVF) that certain parts are not
realistic for a given hardware/OS configuration.  (The traditional
example is, I believe, that it is OK not to supply TEXT_IO for a SBC
which has only 8 segment led's for output devices.)  I have seen the
LMC ruling which states this.

I can't think of any hardware feature (or lack thereof) which would make
the implementation of dynamic address clauses for subprograms unrealistic,
so I guess that EVERYBODY will have to start implementing them SOMEHOW!

This is exactly the point I really started out to make; i.e. that ALL
Ada implementors should be scared s---less that ACVC 1.11... 1.12... or
whatever will actually TEST for this!  I hope that we can get 13.5(5)
nixed before it comes to that.

-- 
Ron Guilmette
National SemiConductor
Internet: rfg@nsc.nsc.com
Uucp: ...{pyramid,sun,amdahl,apple}!nsc!rfg

dee%linus@MITRE-BEDFORD.ARPA (David E. Emery) (06/16/88)

Here's a very legitimate use for a dynamic address clause: C often
returns addresses of objects (becaues C functions cannot return
structures).  The following should be perfectly legal AND ACCEPTABLE
(i.e.  compilers should support this):

	Ada				C 
	
	type rec is record		struct rec {
	  foo : integer;		    int foo;
	  bar : integer;		    int bar;
	end record;			};

					rec *getstuff();

	function getstuff
	    return system.address;
	pragma interface (C, getstuff);

	declare
	  myrec : rec;
	  for myrec use at getstuff;
		-- function call returns system.address.
	  fooval, barval : integer;
	begin
	  fooval := myrec.foo;
	  barval := myrec.bar;
	end;


Obviously, if address clauses were restricted to be static, this
wouldn't work.  They're not, so this should be just fine.  I've tried
this technique on Verdix/Sun, and it works just fine.

				dave emery
				emery@mitre-bedford.arpa

ok@quintus.uucp (Richard A. O'Keefe) (06/17/88)

In article <8806161353.AA17815@linus.MENET> dee%linus@MITRE-BEDFORD.ARPA (David E. Emery) writes:
>Here's a very legitimate use for a dynamic address clause: C often
>returns addresses of objects (becaues C functions cannot return
>structures).

(a) That isn't true; since the days of V7 UNIX C has been able to return
    records.  (There are known problems with the implementation used by
    some compilers, but the facility is present in the language.)  struct
    results and struct assignment are in the draft ANSI standard.

(b) In any case, why not simply return an access value?  Are ADA access
    values required to carry around more information than C pointers?