[comp.sys.sgi] archiving block data subroutines...

jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) (10/22/90)

Hi -

We have a library written in Fortran77 which includes a block data
subroutine.  If we use "ar" to archive the object files of the library,
and then try to compile a program using the resulting "lib???.a" file,
everything works fine EXCEPT the block data subroutine is never executed
(that is, the initializations are not made).  If the block data object file
is linked in explicitly with the fortran compiler, then the initializations
are done.

Archiving the block data subroutine does work elsewhere (at least on computers
running BSD4.3).  It does not work on our SGI Personal Iris, (running
IRIX version 3.2 I believe - but am not positive...  I can find out if it
makes a difference).

Is this a problem with SGI's archiver, or archivers on machines running
System V-like operating systems in general?  We do not have a "ranlib"
program on the SGI;  the "ar" program creates the symbol tables that the
loader needs (we can call normal subroutines that have been archived and
it works fine).

Thanks,
Jeff

--
/******************************************************************************
** Jeff Biesiadecki           ** University of Illinois, Urbana-Champaign    **
** jeffb@aquifer.las.uiuc.edu ** Departments of Geology and Computer Science **
******************************************************************************/

burley@world.std.com (James C Burley) (10/22/90)

In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes:

   Hi -

   We have a library written in Fortran77 which includes a block data
   subroutine.  If we use "ar" to archive the object files of the library,
   and then try to compile a program using the resulting "lib???.a" file,
   everything works fine EXCEPT the block data subroutine is never executed
   (that is, the initializations are not made).  If the block data object file
   is linked in explicitly with the fortran compiler, then the initializations
   are done.

Hi back!  I know nothing about "ar" or "lib???.a" files.  But in Fortran,
there is a specification for forcing the inclusion of a BLOCK DATA program
unit in a program.  It is EXTERNAL, believe it or not.  For example:

      PROGRAM FOO
      EXTERNAL BDATA
      COMMON /X/I
      PRINT *,I
      END

      BLOCK DATA BDATA
      COMMON /X/I
      DATA I/5/
      END

Without "EXTERNAL BDATA", the block data program unit must be explicitly
linked with the program, or whatever wording to that affect is appropriate
(since the standard doesn't really talk about linking).  With it, the linker
should complain if it can't find a block data program unit named BDATA when
linking FOO, and thus should also pull it in from any library it is
searching.

Give this approach a try.  I realize it requires you to modify the code
using the block data program  unit, but that might be a good idea anyway, to
improve its portability.  However, be aware that some nonconforming
implementations of Fortran might do the wrong thing, like assume BDATA must
be a subroutine or function but NOT a block data program unit, so try testing
this approach using, say, the example above (i.e. put BDATA in a library using
"ar" and link it to FOO after compiling both).

James Craig Burley, Software Craftsperson    burley@world.std.com

silvert@cs.dal.ca (Bill Silvert) (10/22/90)

In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes:
>We have a library written in Fortran77 which includes a block data
>subroutine.  If we use "ar" to archive the object files of the library,
>and then try to compile a program using the resulting "lib???.a" file,
>everything works fine EXCEPT the block data subroutine is never executed
>(that is, the initializations are not made).  If the block data object file
>is linked in explicitly with the fortran compiler, then the initializations
>are done.

This is a common (:)) problem which arises from the fact that the linker
looks only for subroutines that are called, and since block data is not
called, it doesn't get linked.  One sure fix is to combine the block
data unit with a subroutine in one file, since the entire file with
both units will then get loaded if the subroutine is called.
-- 
William Silvert, Habitat Ecology Division, Bedford Inst. of Oceanography
P. O. Box 1006, Dartmouth, Nova Scotia, CANADA B2Y 4A2.  Tel. (902)426-1577
UUCP=..!{uunet|watmath}!dalcs!biomel!bill
BITNET=bill%biomel%dalcs@dalac	InterNet=bill%biomel@cs.dal.ca

ddh@hare.cdc.com (Dan Horsfall) (10/22/90)

In article <BURLEY.90Oct22050633@world.std.com> burley@world.std.com (James C Burley) writes:
> In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes:
> 
>    We have a library written in Fortran77 which includes a block data
>    subroutine.  If we use "ar" to archive the object files of the library,
>    and then try to compile a program using the resulting "lib???.a" file,
>    everything works fine EXCEPT the block data subroutine is never executed
>    (that is, the initializations are not made).  If the block data object file
>    is linked in explicitly with the fortran compiler, then the initializations
>    are done.
> 
Keep in mind here a terminology issue: block data subprograms are not 
executable.  They by definition contain no executable code.  They cannot
be "called".

> Hi back!  I know nothing about "ar" or "lib???.a" files.  But in Fortran,
> there is a specification for forcing the inclusion of a BLOCK DATA program
> unit in a program.  It is EXTERNAL, believe it or not.  For example:
> 
>       PROGRAM FOO
>       EXTERNAL BDATA
>       COMMON /X/I
>       PRINT *,I
>       END
> 
>       BLOCK DATA BDATA
>       COMMON /X/I
>       DATA I/5/
>       END
> 
> Without "EXTERNAL BDATA", the block data program unit must be explicitly
> linked with the program, or whatever wording to that affect is appropriate
> (since the standard doesn't really talk about linking).  With it, the linker
> should complain if it can't find a block data program unit named BDATA when
> linking FOO, and thus should also pull it in from any library it is
> searching.
> 

I beg to differ.  EXTERNAL for linking in block data routines is a "fairly
common" extension, but is NOT standard.  Here's the problem at the loader
level:

Block data subprograms contain no executable code.  Thus, they do not contain
an entry point.  A while back, some compiler writers figured out that if they
added an entry point to a block data routine (which actually makes it
executable, tho usually the supporting code is an instant _return).  Now,
having an entry point makes it resolvable by other routines that declare
the same symbol as an external reference.  How to do this in a manner that
doesn't actually execute the code?  Declare the symbol EXTERNAL in some
other routine.

Not all vendors support this mechanism, but this doesn't mean they are 
nonconforming.  MIPS is one of these; mips makes the sgi box; James
Burley's otherwise exemplary solution doesn't apply  to you.  What
you gotta do is force load your block data routines the same way you
force load your main program to start the loading process, e.g.:
   f77 -o xxx  main.o bdata.o libx.a

( In our case here, we use  f77 -o xxx  *.o *.a, and make sure that the
  right *.o's are available.  Kludge, but the only solution.)

--
   Horse
                                       +    Control Data Corporation      
   Dan Horsfall     +1-612-482-4622    +    4201 Lexington Ave North      
   Internet   ddh@dash.udev.cdc.com    +    Arden Hills MN 55126 USA      

doog@travis.ssd.csd.harris.com (Doug Scofield) (10/22/90)

)From article <>, by burley@world.std.com (James C Burley):
)) In article <> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes:
))
)) [ user wishes linker to pull block data from library ]
)
) [ suggests using the EXTERNAL keyword to cause an external reference, ]
) [ which would in theory include the block data subprogram             ]
)
) ... However, be aware that some nonconforming
) implementations of Fortran might do the wrong thing ...

Actually, implementations may do whatever they want in this case.  
Block data subprogram names are defined to be global to the 
execution unit (16.1), and block data names are allowed in EXTERNAL
statements (8.7), but no functional use is described.  In fact, this
is explicitly stated in (B16): 

     The name of a block data subprogram has no explicit use within 
     the FORTRAN language.  It is available for documentation and 
     for possible use within a computer environment.

This "possible use" would include what you require.  An innocuous
global definition of the block data name would be required in the 
block data object, and a global reference would be generated within 
the source object.  Some vendors may be hesitant to do the latter, 
as it requires generating a dummy reference for every unused 
EXTERNAL name.

--
doug scofield                    doog@ssd.csd.harris.com  (preferred)
harris computer systems                  uunet!hcx1!doog

system@alchemy.chem.utoronto.ca (System Admin (Mike Peterson)) (10/23/90)

In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes:
>We have a library written in Fortran77 which includes a block data
>subroutine.  If we use "ar" to archive the object files of the library,
>and then try to compile a program using the resulting "lib???.a" file,
>everything works fine EXCEPT the block data subroutine is never executed
>(that is, the initializations are not made). ...

You can make this work properly on most normal systems (Sun, DEC/Ultrix,
Cray/UNICOS, IBM RS/6000, SGI) by:
- giving the BLOCK DATA routine a unique name.
- putting an 'EXTERNAL blockdataname' statement in the subroutine(s)
  that want the COMMON block to be loaded.

Note that this technique will NOT work reliably on Apollo systems :-(.
-- 
Mike Peterson, System Administrator, U/Toronto Department of Chemistry
E-mail: system@alchemy.chem.utoronto.ca
Tel: (416) 978-7094                  Fax: (416) 978-8775

vjs@rhyolite.wpd.sgi.com (Vernon Schryver) (10/23/90)

In article <27320@shamash.cdc.com>, ddh@hare.cdc.com (Dan Horsfall) writes:
>                                 ...   mips makes the sgi box ...
>    Horse
>                                        +    Control Data Corporation      
>    Dan Horsfall     +1-612-482-4622    +    4201 Lexington Ave North      
>    Internet   ddh@dash.udev.cdc.com    +    Arden Hills MN 55126 USA      


The preceding was probably a typo, but ...

MIPS does not make IRIS's.  Silicon Graphics Computer Systems, Inc. makes
IRIS's.  MIPS makes their own boxes.  I'm not even sure which of the
several silicon foundaries SGI is using for the MIPS R3000 that is probably
in whichever SGI box is being mentioned.  I don't think MIPS is in the
silicon business any more.  I think it's been years since any IRIS
contained any hardware manufactured by MIPS.

It is or at least has been true that packing cases leave Mtn.View loading
docks with labels that do not mention SGI but do say "Cyber".

It is true SGI ships modified versions of MIPS compilers for some but not
all languages.

MIPS &co. are great guys with good machines and all that, but everyone
working at SGI knows they are not as great as SGI.



Vernon Schryver,    vjs@sgi.com

milind@agni.cc.nd.edu (Milind Saraph) (10/23/90)

|>
|>Hi -
|>
|>(stuff deleted)
|>
|>Archiving the block data subroutine does work elsewhere (at least on
computers
|>running BSD4.3).  It does not work on our SGI Personal Iris, (running
|>IRIX version 3.2 I believe - but am not positive...  I can find out if it
|>makes a difference).
|>
|>Is this a problem with SGI's archiver, or archivers on machines running
|>System V-like operating systems in general?  We do not have a "ranlib"
|>program on the SGI;  the "ar" program creates the symbol tables that the
|>loader needs (we can call normal subroutines that have been archived and
|>it works fine).
|>
|>Thanks,
|>Jeff
|>
|>--
|>/*********************************************************************
**********
|>** Jeff Biesiadecki           ** University of Illinois,
Urbana-Champaign    **
|>** jeffb@aquifer.las.uiuc.edu ** Departments of Geology and Computer
Science **
|>**********************************************************************
*********/
                              
This has certainly been a problem on Stellar and Ardent machines (SYS-V like
OS).

-- milind

dik@cwi.nl (Dik T. Winter) (10/23/90)

In article <1990Oct22.130143.29775@cs.dal.ca> bill%biomel@cs.dal.ca writes:
 >                                 One sure fix is to combine the block
 > data unit with a subroutine in one file, since the entire file with
 > both units will then get loaded if the subroutine is called.

Probably sure within this context (Unix systems).  Certainly not sure in
general.  I know of at least one (non Unix) system where this will fail.
In short: there is no solution that will work everywhere, except explicitly
loading the block data subprogram.
--
dik t. winter, cwi, amsterdam, nederland
dik@cwi.nl

sjc@key.COM (Steve Correll) (10/26/90)

In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu>, jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes:
> We have a library written in Fortran77 which includes a block data
> subroutine.  If we use "ar" to archive the object files of the library,
> and then try to compile a program using the resulting "lib???.a" file,
> everything works fine EXCEPT the block data subroutine is never executed
>...
> Is this a problem with SGI's archiver, or archivers on machines running
> System V-like operating systems in general? 

Yes, most Unix System V Release 3 linkers behave differently than most BSD4.3
linkers, in a fashion that is sufficient to explain your problem.

Suppose there is a .o file in the archive library which does not define any
symbol which the linker has seen previously, except for one: an uninitialized
common block. Should the linker bind that .o file into the program on the basis
of that common block alone, even though the .o file does not affect the meaning
of that common block?

Most BSD linkers answer "yes" and most SVR3 linkers answer "no".

The answer _can_ affect the meaning of the program. To sidestep arguments about
the Fortran standard for the moment, consider (sorry) a C example:

file main.c:

  int c;	/* Think of this as uninitialized common */
  main()
    {
    return com1();
    }

file com1.c:

  int c;	/* Think of this as uninitialized common */
  int d = 5;	/* Think of this as initialized common */
  com1()
    {
    return c + d;
    }

file com2.c:

  int c = 6;	/* Think of this as initialized common within blockdata */

Now do the following in /bin/sh:

  cc -c main.c
  cc -c com1.c
  cc -c com2.c
  ar cr lx.a com1.o com2.o
  cc -o main main.o lx.a
  ./main
  echo $?

Most BSD systems will print "11" and most SVR3 systems will print "5" (because
uninitialized common is 0 on Unix systems). If you say:

  nm main

on most BSD systems, both "c" and "d" will have storage class "DATA",
indicating that they have been initialized because com2.o was bound. On most
SVR3 systems, "c" will have storage class "BSS", indicating that it is
uninitialized because com2.o was not bound.

Now as for arguments about the Fortran 77 standard:

James Craig Burley writes:
> ...I believe if you look into
> the history of the F77 standard, you'll find that the reason Page 8-9 lines 30
> and 31 allow block data subprogram names in the EXTERNAL statement was to
> accommodate systems allowing linking of libraries that needed a means to
> allow procedures in a library to specify that they also needed a corresponding
> BLOCK DATA program unit from that same library.
> ...It stands to reason, therefore, that anyone designing a new Fortran system
> and wishing to be standard-conforming would support both the letter and the
> spirit of the standard...any responsible developer would interpret it that
> way...

I am acquainted with language-independent compiler optimizers which delete
unreferenced global imports, causing EXTERNAL BDATA to vanish without a trace.
Perhaps you are not accustomed to such aggressive optimization. Clearly it's
a matter of taste, but around here we tend to regard complaints about such
deletions with the same sympathy we extend to complaints about our not
allocating unSAVEd local variables in memory: if the standard doesn't say you
can rely on it, please don't.

Consider that the Fortran 77 standard says (2.12) that when a procedure
_reference_ is _executed_, the procedure must be "available" (the Fortran 77
circumlocution to avoid talking about "linking"). Can anyone find a provision
in the standard which says that the appearance of a procedure name in an
EXTERNAL statement requires the procedure to be "available"? I can't. In its
absence, I can imagine a perverse user arguing that the following program is
standard-conforming even if X is not available:

	EXTERNAL X
	END

and complaining that a processor which refuses to construct an executable
program in the absence of X fails to conform to Fortran 77!
-- 
sjc@key.com or ...{sun,pyramid}!pacbell!key!sjc 		Steve Correll

burley@world.std.com (James C Burley) (10/26/90)

In article <2208@key.COM> sjc@key.COM (Steve Correll) writes:

   James Craig Burley writes:
   > ...I believe if you look into
   > the history of the F77 standard, you'll find that the reason Page 8-9 lines 30
   > and 31 allow block data subprogram names in the EXTERNAL statement was to
   > accommodate systems allowing linking of libraries that needed a means to
   > allow procedures in a library to specify that they also needed a corresponding
   > BLOCK DATA program unit from that same library.
   > ...It stands to reason, therefore, that anyone designing a new Fortran system
   > and wishing to be standard-conforming would support both the letter and the
   > spirit of the standard...any responsible developer would interpret it that
   > way...

   I am acquainted with language-independent compiler optimizers which delete
   unreferenced global imports, causing EXTERNAL BDATA to vanish without a trace.
   Perhaps you are not accustomed to such aggressive optimization. Clearly it's
   a matter of taste, but around here we tend to regard complaints about such
   deletions with the same sympathy we extend to complaints about our not
   allocating unSAVEd local variables in memory: if the standard doesn't say you
   can rely on it, please don't.

   Consider that the Fortran 77 standard says (2.12) that when a procedure
   _reference_ is _executed_, the procedure must be "available" (the Fortran 77
   circumlocution to avoid talking about "linking"). Can anyone find a provision
   in the standard which says that the appearance of a procedure name in an
   EXTERNAL statement requires the procedure to be "available"? I can't. In its
   absence, I can imagine a perverse user arguing that the following program is
   standard-conforming even if X is not available:

	   EXTERNAL X
	   END

   and complaining that a processor which refuses to construct an executable
   program in the absence of X fails to conform to Fortran 77!
   -- 
   sjc@key.com or ...{sun,pyramid}!pacbell!key!sjc 		Steve Correll

I am accustomed to extremely aggressive optimization, both that which has
been implemented and that which I've only thought about.

The program you show above, "EXTERNAL X;END", is indeed standard-conforming
even if X is not available, because X is not necessarily a procedure: in fact
it appears the standard requires that it must be a BLOCK DATA subprogram.
(Because in the main program unit, it is not referenced as a subroutine or
function, and a BLOCK DATA subprogram is the only alternative.)  Unfortunately,
the standard does not appear to specify the effect of specifying a BLOCK DATA
subprogram name in an EXTERNAL statement.  So it appears that your mythical
user complaining about a processor refusing to construct an executable
program in the absence of X indeed has a point: it is a valid program, and
X need not be present, even though I would argue a reasonable implementation
should complain that there is no BLOCK DATA X (via an error message from,
perhaps, a multi-language linker requiring the user to look up the message
in the Fortran book to yield the explanation that perhaps a BLOCK DATA X
is missing).

However, as I pointed out in my original posting, the only reasonably way
for an implementation to deal with "EXTERNAL FOO" where FOO is not referenced
anywhere else in the same program unit is for it to assume FOO is a BLOCK DATA
program unit and to ensure that, if it indeed turns out that FOO is found to
be a BLOCK DATA program unit, its initial values for variables in COMMON are
used for the program.  If FOO turns out to be a subroutine or function, an
implementation is free to ignore it, if it is capable of doing that while
still dealing with the possible BLOCK DATA FOO case instead.

Now, you can play language lawyer games -- like the company that said their
implementation was standard-conforming even though the STOP statement did
not in fact stop the program, because the standard didn't actually specify
what happens the moment after the program is "stopped" -- and say that an
implementation is standard-conforming that totally ignores EXTERNAL FOO
where FOO is otherwise unreferenced in the program unit.

However, if you are taking things this literally from a standards
perspective, then please note that there is NO STANDARD WAY to initialize
variables in common!  According to the standard, that can ONLY be done
via BLOCK DATA.  And a system that provides some mechanism whereby BLOCK DATA
can be ignored (the "library problem" that started all this), and yet
refuses to honor a clear accommodation in the standard to deal with the
problem, fails to honor the spirit of the standard, just as does one that,
when running a program saying "PRINT *,2.0*3.0", outputs "2.0" because
the standard doesn't actually specify precision requirements.

After all, if subroutines and functions need only be "available" when they
are actually "referenced" at run time, then (unless there's some wording to
override this assumption in the standard that I can't remember seeing offhand),
the same goes for BLOCK DATA in a system that implements everything using
libraries.  Yet there is NO WAY to "reference" a BLOCK DATA subprogram except
via the "EXTERNAL FOO" construct.

(And note that your reference to complaints about unSAVEd variables not
being SAVEd is, in my opinion, an invalid comparison in this context.
The spirit of the standard regarding BLOCK DATA is as I state above; whereas
the standard clearly states that you can't depend on the value of an
unSAVEd variable between procedure invocations.  People complaining about
a system not honoring the EXTERNAL FOO convention for ensuring the linking-in
of a BLOCK DATA FOO residing in a library have a very legitimate gripe,
language-lawyer games notwithstanding.  People who complain about unSAVEd
variables not retaining their values between procedure invocations are just
plain wrong; but note that many implementations nevertheless provide command-
line qualifiers to effectively force the SAVEing of all appropriate
variables, so given that so many implementations bend over backwards to
accommodate incorrect or very old code, why not deal with the relatively
trivial case of EXTERNAL FOO possibly referring to a necessary BLOCK DATA FOO?)

James Craig Burley, Software Craftsperson    burley@world.std.com