[M3devel] addresses of constants?

Rodney M. Bates rodney_bates at lcwb.coop
Mon Aug 6 19:40:21 CEST 2012


You probably already know this, but, from 2.7:

   ADR (VAR x: Any) : ADDRESS
   ...
   ADR(x) is the address of the variable x. The actual argument must be a designator but need not be writable.

And from 2.6.3:

   An identifier is a writable designator if it is declared as a variable, is a VAR or VALUE parameter, is a local of a
   TYPECASE or TRY-EXCEPT statement, or is a WITH local that is bound to a writable designator. An identifier is a
   readonly designator if it is a READONLY parameter, a local of a FOR statement, or a WITH local bound to a nondesignator
   or readonly designator.

I'm speculating, but confidently, that the reason for the designator restriction
is to have an implementation-independent rule that ensures the value would be
in memory, and thus have an address, regardless of whether ADR is applied to
it or not, The ADR could happen in a separate compilation from the declaration,
and its existence be unknown at least until the main program was compiled.

This way, compiler writers have the option of putting any constant in
immediate instruction fields, if the target machine has them, without risk of
undermining source code that compiled and ran fine on a different machine
or with a different compiler.

Even if it's sure to be in memory, allowing ADR(SomeConstant) also would
open up the possibility of a constant that wasn't constant, a la FORTRAN.
Yeah, I know it's already unsafe code anyway, but that would be an
additional form of unsafety with scarcely an imaginable benefit.

I'd just make it a VAR and put it inside a module.  You would only have
to verify that that one module didn't change it.  It's possible a smart
enough compiler would initialize right in the variable in the executable
and not have to copy it.

BTW, VAR ZLIB_VERSION = "1.0.4"; and ADR(ZLIB_VERSION[0])
appears to have another problem.  It assumes the representation of "1.0.4"
is the same as, or at least contains

ARRAY [0..5] OF char{
ORD('1'), ORD('.'), ORD('0'), ORD('.'), ORD('4'), 0};

which it also looks like your modified UgzipP.deflateInit would expect.
This happens to be true in pm3, but not cm3.  Without debating the
merits of various representations of TEXT literals, it would make
for implementation-dependent code in any case.

On 08/05/2012 10:48 PM, Jay K wrote:
> Ugzip.m3 does an unnecessary heap allocation and copy.
>
>
> Here I have changed it to avoid the heap allocation.
> But it still makes a copy.
>
> How can I fix that?
>
> It seems ADR cannot be applied to constants?
>
> CONST
>    ZLIB_VERSION = ARRAY [0..5] OF char{
>                   ORD('1'), ORD('.'), ORD('0'), ORD('.'), ORD('4'), 0};
>
> This works but still is inefficient:
>
> PROCEDURE deflateInit(strm: z_stream_star; level: int): int =
>    VAR version := ZLIB_VERSION;
>    BEGIN
>      RETURN UgzipP.deflateInit_(strm, level, ADR(version[0]), BYTESIZE(z_stream));
>    END deflateInit;
>
>
> I'd like to say ADR(ZLIB_VERSION[0]) or ADR(ZLIB_VERSION);
> const ZLIB_VERSION = "1.0.4"; and ADR(ZLIB_VERSION[0]) of that.
>
>
>   - Jay




More information about the M3devel mailing list