[comp.lang.c] Pragmas

gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/20/87)

In article <3865@uw-june.UUCP> pardo@uw-june.UUCP (David Keppel) writes:
>>In article <3855@uw-june.UUCP> pardo@uw-june.UUCP (David Keppel) writes:
>>>... how about adding a "pragma" which looks like a procedure call.
[I had previously responded:]
>>... I don't understand just what it is that you are proposing.
>By adding even a small pragma mechanism to the language ...

Ah, now I see why I didn't understand.  The proposed ANSI C has had pragmas,
in the form
	#pragma	...stuff...
, for quite some time now.  You're suggesting a different syntax, so that
the preprocessor can be used to disable pragmas.

mccarrol@topaz.rutgers.edu (<MC>) (12/24/87)

With all of the discussion lately about #pragmas vs noalias, I
thought I'd ask a simple ( and probably stupid) question:

	What is a pragma, and what is the function of #pragma in C?

		<MC>
-- 
Mark C. Carroll                   | a man in black on a snow white horse.
Rutgers University CS Student     | a pointless life has run its course.
ARPA: Carroll@aim.rutgers.edu     | the red rimmed eyes, the tears that run
UUCP: mccarroll@topaz.rutgers.edu | as he fades into the setting sun

cr@hpcilzb.HP.COM (Cindy Roberts) (12/30/87)

>	What is a pragma, and what is the function of #pragma in C?

I would also like a clue!

	-Cindy

kgregory@bbn.COM (Keith D. Gregory) (01/01/88)

In article <1620005@hpcilzb.HP.COM> cr@hpcilzb.HP.COM (Cindy Roberts) writes:
>
>>	What is a pragma, and what is the function of #pragma in C?
>
>I would also like a clue!

A #pragma statement is "a compiler non-specific way of indicating compiler
specific actions". . . a portable way of saying that you have non-portable
code.
  
On the surface, this seems to be a good idea - if your compiler sees a #pragma
that it doesn't recognize, then it abends.  If it does recognize a pragma, then
it may (or may not) shift into a special processing mode.
  
  
Of course, as far as I can tell, there are absolutely no controls on the use
of #pragma directives.  Two compilers could use the same directive to do 
different things (picture #pragma assembly, to indicate the use of inline A/L),
and fail radically when code for one is compiled under the other.
  
So, to all the people "who really know" . . . is there any good reason for
#pragma's existance (I don't consider the above mentioned reason to be "good")
 
-kdg

pardo@uw-june.UUCP (David Keppel) (01/01/88)

["A pragma is a non-specific way of indicating compiler-spcific actions" . . .
  a portable way of saying that you have non-portable code]

Pragmas are not _necessarily_ portability issues.  For example the PACKED
keyword in Pascal is a "pragma" saying that data is to be stored in a space-
efficient (rather than a time-efficient) way.  A compiler can safely ignore
the PACKED "pragma" as long as the programmer didn't write any code that
depends on the code being packed.

Note, BTW, that PACKED data can be *faster* to copy than unpacked data,
so what I said above is a lie - it doesn't really mean "instead of time-
efficient", but that's the general idea.

 ;-D on  (I just PACKED my bags and my toothbrush access time went up)  Pardo

minow@thundr.dec.com (Martin Minow THUNDR::MINOW ML3-5/U26 223-9922) (01/03/88)

bbn!kgregory asks for examples of #pragma usage.  Here are a few:
 
-- Decus C has compiler-specific keywords to determine storage allocation
   (program sections) -- this let you write data into specific areas
   that were resolved to absolute base addresses by the linker.  This
   is essential if you are writing a program that will subsequently
   be run from ROM; you must force code and tables into read-only memory
   and non-static data into ram.  This also let us develop a facility
   that called specific functions at the start and/or end of execution.
   The function registry mechanism used program sections to manage
   a table of routines to call: all of the mechanism was done by the
   compiler.  The Draft Standard has an "atexit()" registry that is
   managed by explicit calls by the running program.  Decus C has
   both "atexit" and "atentrance" which are triggered by the inclusion
   of the module, and require no programmer intervention.
 
-- On some architectures, such as the Vax, certain instructions may
   not be used to access device registers.  A statement such as
       #pragma device_register foo, bar;
   might be useful to prevent certain optimizations.  Note that the
   architectural restriction goes beyond what "volatile" can accomplish.
 
-- On architectures such as the 80x86 family, one can achieve useful
   optimization by adding "near" and "far" pragmas.
 
-- One might use #pragma's to enable/disable debugging or self-testing
   code.
 
While all of the above can be achieved by using implementation-specific
keywords (beginning with _), #pragma is a useful addition to the language.
 
According to the Draft Standard, unknown pragmas are to be ignored
(section 3.8.6 of the Aug. '87 draft).  Because it doesn't distinguish
mistakes from typographical errors, this is a mistake, and one that the
Committee seems inordinately fond of: they rejected my request to
flag unknown pragmas as errors.

The Gnu compiler "recognizes" all pragmas, causing them to run Towers
of Hanoi to a depth of 64. This is proper usage per the Draft Standard.
 
Martin Minow
minow%thundr.dec@decwrl.dec.com
decvax!decwrl!dec-rhea!dec-thundr!minow
 
========================================================================
Received: by decwrl.dec.com (5.54.4/4.7.34)
	id AA06740; Fri, 1 Jan 88 19:31:42 PST

dhesi@bsu-cs.UUCP (Rahul Dhesi) (01/03/88)

In article <8801021358.AA15890@decwrl.dec.com> minow@thundr.dec.com (Martin 
Minow THUNDR::MINOW ML3-5/U26 223-9922) writes:
>According to the Draft Standard, unknown pragmas are to be ignored
>(section 3.8.6 of the Aug. '87 draft).  Because it doesn't distinguish
>mistakes from typographical errors, this is a mistake, and one that the
>Committee seems inordinately fond of: they rejected my request to
>flag unknown pragmas as errors.

Agreed.  What we really need is a pragma that tells the compiler to
ignore unrecognizes pragmas, and the default should be to flag
unrecognized pragmas as errors.

Unfortunately, it has been traditional (e.g. Pascal and Ada) for
compilers to ignore unrecognized pragmas so ANSI is simply following
well-trodden footsteps.  This may not get fixed until a missile is
actually lost in space due to a misspelled pragma.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

jgm@K.GP.CS.CMU.EDU (John Myers) (01/03/88)

In article <8801021358.AA15890@decwrl.dec.com> minow@thundr.dec.com (Martin Minow THUNDR::MINOW ML3-5/U26 223-9922) writes:
>According to the Draft Standard, unknown pragmas are to be ignored
>(section 3.8.6 of the Aug. '87 draft).  Because it doesn't distinguish
>mistakes from typographical errors, this is a mistake, and one that the
>Committee seems inordinately fond of: they rejected my request to
>flag unknown pragmas as errors.
>
>The Gnu compiler "recognizes" all pragmas, causing them to run Towers
>of Hanoi to a depth of 64. This is proper usage per the Draft Standard.
> 
Unfortunately, this feature of the Gnu C preprocessor went away in the
latest version, 1.16.  It now passes #pragma statements through untouched.

Actually, a conformant compiler could "recognize" all pragmas not otherwise
defined by the compiler as a command to issue an error.

				_.John G. Myers

rjchen@phoenix.Princeton.EDU (Raymond Juimong Chen) (01/03/88)

In a famous article, minow@thundr.dec.com (Martin Minow) said:
>According to the Draft Standard, unknown pragmas are to be ignored
>(section 3.8.6 of the Aug. '87 draft).  Because it doesn't distinguish
>mistakes from typographical errors, this is a mistake, and one that the
>Committee seems inordinately fond of: they rejected my request to
>flag unknown pragmas as errors.

Why not flag unknown #pragmas as warnings?  This would allow files to be
compiled, while letting the user know that something may be amiss.
If the user sees things like
	warning: unknown pragma directive: memory_model
	warning: unknown pragma directive: asm
	warning: unknown pragma directive: mispelled
s/he can take appropriate action for each one.  (The first can probably
be ignored safely; the second will cause hair to be pulled out; the third
is the kind of thing we need to catch lest our next spacecraft land in a
rock garden instead of a flat surface.)

Also, has dpANS (or however you capitalize it) made any attempts at
standardizing #pragmas?  To the extent of "If your compiler accepts
#pragma sneeze, then the sneeze option must mean the following: ...",
I mean.  Is this a good idea?  Is it practical?
-- 
Raymond Chen	UUCP: ...allegra!princeton!{pucc|phoenix}!rjchen
		BITNET: 6101695@pucc, rjchen@pucc
		ARPA: rjchen@pucc.PRINCETON.EDU
"Say something, please!  ('Yes' would be best.)" - The Doctor

ok@quintus.UUCP (Richard A. O'Keefe) (01/03/88)

In article <8801021358.AA15890@decwrl.dec.com>,
minow@thundr.dec.com (Martin Minow THUNDR::MINOW ML3-5/U26 223-9922)
gives some examples of #pragmas.
(1) > (program sections) -- this let you write data into specific areas
    > that were resolved to absolute base addresses by the linker.
(2)   declaring variables to be device registers
    > #pragma device_register foo, bar;
(3) > On ... the 80x86 family ... "near" and "far" pragmas.
(4) > One might use #pragma's to enable/disable debugging
    > or self-testing code.

The preprocessor (remember the pre-processor? all and only # lines
are to be handled by the preprocessor, which has usually been
implemented as a **SEPARATE** program) is the wrong place to handle
each of these things.

(1) To the extent that I understand it, this is a task for the loader.
    The System V "COFF" loader will let you do all of this and more.
    So does the VMS loader.
(2) The appropriate way to handle this is with
	pragma(device_register) struct devreg foo;
    or whatever.  The preprocessor is for handling file inclusion,
    conditional inclusion, and macro definition and expansion.  Not
    for giving half of a declaration!
(3) Many 80x86 C compilers already have 'near' and 'far' as keywords,
    and I really don't think they are going to go away.  Let's face
    it, "char *near" is a 16-bit (8086) or 32-bit (80386) data type,
    and "char *far" is a 32-bit (8086) or 48-bit (80386) data type,
    and something that fundamental belongs in the language, not in
    the preprocessor.  So the appropriate thing to do is NOT to say
	#pragma near fred
	#pragma far jim
	char *fred, *jim;
    but
	char *pragma(near) jim;
	char *pragma(far) fred;
(4) This IS an appropriate use of the preprocessor, but we already
    have #if.  The way to do it is e.g.
	#if	DEBUG
	void display_thing(const struct foo *p)
	    { ... }
	#else
	#define display_thing(x) (void)(x)
	#endif

It used to be the case back in Version 7 that there were two independent
programs:
	the C preprocessor
	the C compiler
When I say that they were independent, I mean that
(a)	the C preprocessor was available as a separate program which
	could be called directly and could be used as a front-end to
	ANYTHING with C-like lexical structure.  E.g. Yacc, Ratfor,
	... 

(b)	the C compiler could be invoked without using the C preprocessor.
	(If the first character wasn't a #, the preprocessor was not used.)
	Every facility of the C language (including all the libraries)
	could be accessed without using the preprocessor.

In the interests of portability, a lot of things have been shunted off
into "standard" header files.  With faster machines than PDP-11/34s,
and with portability-via-standard-macros as a desideratum, property (b)
is not very important any more.  But property (a) is still useful.  I
have often used the C preprocessor as a front-end to other tools, and
very useful it is.  It seems to me that it would be a serious mistake
to FORCE the preprocessor to be strongly coupled to the compiler.

Now, is #pragma something which forces the preprocessor to be strongly
coupled to the compiler, or not?  Well, if #pragma can be used to
declare properties of identifiers, either the preprocessor has to be
built into the compiler or else it has to write something into its
output stream which recodes the information and the compiler has to
reparse it.  In this latter case, there is a strong coupling between
the preprocessor and its particular compiler, because they have to
agree on how the pragma information is recoded.

The trouble with declaring properties of identifiers in the preprocessor
is the interaction of those declarations with C's scope rules.  Suppose
I say

	int fred;			/* 1 */
	void jim()
	#pragma device_register fred
	    {
		static int fred;	/* 2 */
		...

Which fred was affected?  I can think of at least four different
interpretations, and each of them is "natural" and "obvious" given
a different method of coupling the preprocessor and compiler.

Now since the compiler is going to have to do something with this
information anyway, the obvious thing to do is to be efficient and
have only ONE program know about it, namely the compiler, and write

	pragma(device_register) int fred;	/* 1 */
	void jim()
	    {
		static int fred;
or
	int fred;
	void jim()
	    {
		static pragma(device_register) int fred; /* 2*/
and make it absolutely clear which one we mean?

I mean, let's face it, playmates, handling pragmas in the pre-processor
makes about as much sense as handling "long" or "short" there.

flaps@dgp.toronto.edu (Alan J Rosenthal) (01/04/88)

ok@quintus.UUCP (Richard A. O'Keefe) writes:
 >Now, is #pragma something which forces the preprocessor to be strongly
 >coupled to the compiler, or not?  Well, if #pragma can be used to
 >declare properties of identifiers, either the preprocessor has to be
 >built into the compiler or else it has to write something into its
 >output stream which recodes the information and the compiler has to
 >reparse it.  In this latter case, there is a strong coupling between
 >the preprocessor and its particular compiler, because they have to
 >agree on how the pragma information is recoded.

How about having the preprocessor just pass them through?  The compiler
and the preprocessor already agree on how some lines beginning with #
are passed through, namely the "# line file" lines.  Just typing
"/lib/cpp" gives me one.  /lib/cpp will also pass them through.

 >The trouble with declaring properties of identifiers in the preprocessor
 >is the interaction of those declarations with C's scope rules.  Suppose
 >I say
 >
 >	int fred;			/* 1 */
 >	void jim()
 >	#pragma device_register fred
 >	    {
 >		static int fred;	/* 2 */
 >		...
 >
 >Which fred was affected?  I can think of at least four different
 >interpretations, and each of them is "natural" and "obvious" given
 >a different method of coupling the preprocessor and compiler.

After ANSI standard C hits the streets, when you type "man cc", it will
probably have a section describing pragmas, or at least it should.  It
will say something like "'#pragma device_register id' means that the
next occurrence of 'id' is a device register".  Or wherever it was you
learned of the pragma's meaning in the first place.  No problem.

Two further comments on this:
    1. that's a terrible construct anyway.
    2. I can't think of your three other "natural" interpretations.

-- 
"Bill Joy uses EMACS."  - D. Hugh Redelmeier

ok@quintus.UUCP (Richard A. O'Keefe) (01/04/88)

In article <1988Jan3.162343.1697@jarvis.csri.toronto.edu>,
flaps@dgp.toronto.edu (Alan J Rosenthal) replied my message about #pragma:

> How about having the preprocessor just pass them through?  The compiler
> and the preprocessor already agree on how some lines beginning with #
> are passed through, namely the "# line file" lines.  Just typing
> "/lib/cpp" gives me one.  /lib/cpp will also pass them through.

Passing #pragmas through to the compiler means that
(1) /lib/cpp	has to parse stuff which is significant to the C
		compiler, and ONLY to the C compiler.
(2) /bin/cc	has to parse something like the pragma(..) construct
		ANYWAY, the user just doesn't get told what it looks
		like (and so doesn't know how to *avoid* it).

#line is a different case.  The whole POINT of the preprocessor is to
drop lines, expand macros, and generally do all sorts of things that
can make it hard for the compiler to work out where anything came from.
In fact, as your example shows, the main function of # <lino> <file>
is not to be passed through by the preprocessor, but to be generated
by the preprocessor.  I have never written a # <lino> <file> in my
life, but the preprocessor has made millions for me, BECAUSE THAT IS
PART OF ITS JOB.  (And it can be told not to.  Try /lib/cpp -P)
#line is **related to cpp's FUNCTION**.
#pragma is not related to the function of the *preprocessor*.

If you are going to pass #pragmas through to the compiler in some
fashion, why not reserve one (count them, ONE) keyword for the thing
that gets passed through, and standardise that?  Something of the
sort apparently has to be around anyway, and having just one keyword
makes it easy to avoid.

Perhaps I can make it a little bit clearer why, if pragmas are going
to be in the language, having
	pragma(system-dependent-parenthesis-balanced-stuff)
as something that can appear where 'noalias' would have been allowed,
is a better way to go than having #pragma in the pre-processor.

One of the things one wants to do with a program is to analyse it.
For example, one would like to produce cross-referencers, static
call graph analysers, "software metrics" tools, &c &c.  We would
like to write such tools ONCE for "ANSI C".

The easiest way to hack this is
	cc -E source.c | analyser
which means that your analyser doesn't have to be a preprocessor as
well as a parser!  The # <lino> <file> lines generated by the
preprocessor tell you everything you need to know about where things
came from (if you are doing a cross referencer or dependency analysis).

If the "pragma" construct is defined as pragma(..) in the compiler
language, then each tool has to be prepared to skip a parenthesis
balanced sequence of tokens after pragma() but can otherwise ignore
the construct.  But if #pragma is a pass-through (as some quite
undocumented form) then I can't defend my tool against it, because
I don't know what the passed-through form is going to look like.

Now the ANSI committee has rightly chosen not to specify the behaviour
of the preprocessor as a separate program, or even that it IS a
separate program, or even that "cc -E" should work.  But they surely
should not go out of their way to make life hard for people who want
to write program analysis tools!

> After ANSI standard C hits the streets, when you type "man cc", it will
> probably have a section describing pragmas, or at least it should.  It

I have access to a compiler NOW on a S5.3 machine that has #pragma.
The manual does NOT tell me what #pragma does.

> will say something like "'#pragma device_register id' means that the
> next occurrence of 'id' is a device register".  Or wherever it was you
> learned of the pragma's meaning in the first place.  No problem.

Yes, that will answer the "scope" problem.  But my actual viewpoint is
that I would like to be able to write tools that will work in the
presence of pragmas(), without even having heard of the machine or its
operating system, let alone having seen the compiler manual.  I can do
this for ADA.  Why not for C?

> Two further comments on this:
>     1. that's a terrible construct anyway.
>     2. I can't think of your three other "natural" interpretations.
Two rejoinders:
(1) #pragma device_register fred   was *your* example.
    I merely pointed out the problem.
(2) Thank you.  I was hoping for that.  I bet there are at least
    three implementors out there who also can't think what the
    three "other" interpretations are, and yours is one of the ones
    they can't think of.  Which is why
	#pragma <property> <identifier> ;
    IS a terrible construct.

sms@sugar.UUCP (Stanley M. Sutton) (01/05/88)

I've yet to run into a vendor that hasn't "improved" a language
with extensions for his particular hardware.  If used properly, a 
pragma may be a useful way to extend a language that warns the code
reader that something non-standard is being used.  Code is almost always
developed with two purposes in mind.  The first is to solve a problem;
the second, to allow someone else to understand both the problem to be
solved, and the actual solution.
   
Portability is a design criteria for some projects, efficency for others,
and "getting it working" for others.  Pragmas can be used for all
three goals, if they are used and implemented correctly.  
   
For example, the use of inline assembly.  A module can be developed in
portable C until the application is functional.  Time studies may then 
be performed on the code.  If a memory transfer operation is taking a 
significant portion of the time of the application, the actual memory
transfer may be done in assembly to take advantage of hardware specific
features (such as the blitter and/or DMA controller on an Amiga) using
#ifdef ... #else ... #endif to improve performance.
   
Almost any feature available to a programmer can be used or abused.  The
feature is not inheriently good or bad.  It's the purpose the programmer
uses it to accomplish that is good or bad.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/06/88)

In article <17196@topaz.rutgers.edu> mccarrol@topaz.rutgers.edu (<MC>) writes:
>	What is a pragma, and what is the function of #pragma in C?

A "pragma" is some advice to the compiler outside the scope of the
language proper.  Ada has these.  Typically, pragmas are interpreted
in an implementation-specific way.  Typical usages include specifying
various optimization preferences, producing listings, aiding debugging,
etc.

The proposed ANSI C provides a #pragma preprocessing directive but
leaves the definition of its effects up to the implementation.  My
version of the Reiser C preprocessor accepts #pragma but ignores it.

The main reason #pragma is not suitable for "noalias" is, as I showed
in an earlier posting, the "noalias" property has potentially visible
and important effect on the computation, depending on the code.  Such
code is "illegal", under the "noalias" approach, but it would have to
be permitted if #pragma were used.  A #pragma is not supposed to
change the interpretation of the virtual-machine semantics of the code.

At least, that's my interpretation of what's going on here.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/06/88)

In article <1766@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>This may not get fixed until a missile is
>actually lost in space due to a misspelled pragma.

Since a #pragma is not supposed to change the abstract "virtual
machine" operation, it's hard to see how this could happen.

At the rate the USA is going, it's going to be a long time before
a missile is actually fired into space!

dsill@NSWC-OAS.arpa (Dave Sill) (01/07/88)

Doug Gwyn writes:
>In article <1766@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>>This may not get fixed until a missile is
>>actually lost in space due to a misspelled pragma.
>
>Since a #pragma is not supposed to change the abstract "virtual
>machine" operation, it's hard to see how this could happen.

Where does it say this?  For the benefit of those without a copy of
the dpANS, this is what it (Oct '86) says about pragmas:

---------------
3.8.6 Pragma Directive

Semantics

  A #pragma preprocessing directive causes the implementation to
behave in an implementation-defined manner.  Any pragma that is not
recognized by the implementation is ignored.
---------------

The rationale says:

---------------
3.8.6 Pragma Directive

The #pragma directive has been added as the universal method for
extending the space of directives.
---------------

Don't flame me for quoting the above, I couldn't find a copyright
notice.

>At the rate the USA is going, it's going to be a long time before
>a missile is actually fired into space!

Unless I'm mistaken, intercontinental ballistic missiles are fired
through space.  I certainly hope it's going to be a long time before
such a missile is fired.

==========
The opinions expressed above are mine.

Which is worse: ignorance or apathy?  Who knows?  Who cares?

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/07/88)

In article <11137@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes:
>Doug Gwyn writes:
>>In article <1766@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>>Since a #pragma is not supposed to change the abstract "virtual
>>machine" operation, it's hard to see how this could happen.
>
>Where does it say this?

This is not explicitly stated; rather, it is deduced as follows:

The requirements for a conforming implementation are defined by
the standard as a whole, not just some portion of the standard taken
out of context.  A conforming implementation must simultaneously
meet all specified constraints.  Although the behavior of #pragma
is not spelled out, other than requiring each implementation to
describe its interpretation of pragmas, other portions of the
standard impose constraints on the C language.  If an implementation
were to attempt to make its interpretation of some #pragma result in
behavior counter to that specified in the rest of the standard,
	#pragma Pascal { The rest of this file is Pascal syntax! }
for example, then the total total set of rules is self-contradictory;
that is, such an implementation logically cannot be standard
conforming.  I chose the most reasonable example I could think of
for a radically-contradictory pragma; if I had introduced a more
subtle relevant one such as
	#pragma noalias variable_name
then the point would have been harder to see, but it's logically
the same issue.

In fact, I used to think that the presence of #pragma "spoiled"
the code, so that no portable application could ever contain a
#pragma directive.  But some other X3J11 committee members finally
convinced me that pragmas could not violate the abstract machine
semantics specified by the rest of the standard.  I should note
that at least one committee member has indicated that he still
thinks the way I used to.  If in fact I now have the intended, or
at least the consensual, understanding of this, then it would
probably be wise to have a discussion like the above in the
Rationale document.

mwm@eris.BERKELEY.EDU (Mike (My watch has windows) Meyer) (01/07/88)

In article <5724@ccv.bbn.COM> kgregory@ccv.bbn.com (Keith D. Gregory) writes:
<So, to all the people "who really know" . . . is there any good reason for
<#pragma's existance (I don't consider the above mentioned reason to be "good")

I don't know about "a good reason for #pragma's existence," but I *do*
know of a case where they were put to good use.

AmigaDOS supports shared libraries. The interface is a jump table into
the library, with a pointer to the table being stored in a variable of
a known name. In assembly, the calling sequence looks like:

	move.l	<args>,<registers>	; arguments
	movea.l	SomeLibrary,a0		; address table
	jsr	offset(a0)		; and go there

To use these things from C (vital - the OS interface looks like shared
libraries), it's normally done the same way as Unix: a stub routine in
assembler that takes the C arguments, puts them in the right
registers, and then jmps/jsrs to the real routine.

The latest version of the Lattice C compiler has a pragma for dealing
with shared libraries. It basically looks like:

#pragma	routinename libraryname offset	registers

This makes it generate an inline-call as the above, rather than a call
to a C stub that does the above. This means you get faster code, and
possibly slightly smaller code (depends on the details of code
generation & calling sequences I haven't looked at closely - going to
find out, though).

What makes the useage "good" is that when you include the header file
with the prototypes for the functions in a library, you get pragmas
for all the functions, too. This means that I can use the feature, and
the code will work on compilers that don't support this feature
without change. Or if they support it in another (though similar) way,
it should work.

I can't see a good way to do this without something similar to
pragmas. Wiring the names into the compiler means you can't get your
own libraries done that way (and is probably much nastier than the
above) without changing the compiler. Not good.

	<mike
--
Estant assis, de nuit secrette estude,			Mike Meyer
Seul, repose sur la selle d'airain,   			mwm@berkeley.edu
Flambe exigue, sortant de solitude,   			ucbvax!mwm
Fait proferer qui n'est a croire vain.			mwm@ucbjade.BITNET

msb@sq.uucp (Mark Brader) (01/08/88)

On the matter of portability of programs with #pragma lines,
Doug Gwyn writes:

> This is not explicitly stated; rather, it is deduced ...
> In fact, I used to think that the presence of #pragma "spoiled"
> the code, so that no portable application could ever contain a
> #pragma directive.  But some other X3J11 committee members finally
> convinced me that pragmas could not violate the abstract machine
> semantics specified by the rest of the standard.  I should note
> that at least one committee member has indicated that he still
> thinks the way I used to.  If in fact I now have the intended, or
> at least the consensual, understanding of this, then it would
> probably be wise to have a discussion like the above in the
> Rationale document.

It seems to me that users of a Standard should not have to make
deductions of such complexity that members of the Committee can
get them wrong.  This matter should be clarified right in the
Standard, even if it does create some redundancy, or at the most
in a footnote, and not tucked away in the Rationale.

Mark Brader				"C takes the point of view
SoftQuad Inc., Toronto			 that the programmer is always right"
utzoo!sq!msb, msb@sq.com				-- Michael DeCorte

dhesi@bsu-cs.UUCP (Rahul Dhesi) (01/08/88)

In article <6939@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) 
writes:
>In article <1766@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>>This may not get fixed until a missile is
>>actually lost in space due to a misspelled pragma.
>
>Since a #pragma is not supposed to change the abstract "virtual
>machine" operation, it's hard to see how this could happen.

Consider:  If the programmer used a #pragma at all, he was probably
trying to cause some detectable change in the compilation or execution
of a program.

Perhaps one would use a pragma to tell a compiler to use 32-bit
pointers (say on an 8086 architecture), thus allowing a data-structure
created at runtime, holding coordinates of Soviet missile stations, to
grow to a reasonable limit.  Or ask the compiler to optimize a routine
by unrolling an inner loop so it runs fast enough to keep up with an
anticipated salvo of Soviet missiles, so that one's Star Wars defense
system might work.

The point being that semantically equivalent virtual machines could
still be remarkably different in speed and memory capabilities.  And in
a critical application, an unrecognized pragma might make all the
difference.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

barmar@think.COM (Barry Margolin) (01/08/88)

In article <6920@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>The main reason #pragma is not suitable for "noalias" is, as I showed
>in an earlier posting, the "noalias" property has potentially visible
>and important effect on the computation, depending on the code.  Such
>code is "illegal", under the "noalias" approach, but it would have to
>be permitted if #pragma were used.  A #pragma is not supposed to
>change the interpretation of the virtual-machine semantics of the code.
>At least, that's my interpretation of what's going on here.

That's not my interpretation of noalias.  Noalias is merely a way to
point out a potential optimization.  Since a compiler that doesn't
know how to perform this optimization could validly ignore noalias
declarations, it cannot affect the semantics of the code.  Any program
tha behaves differently depending on whether a variable was declared
with noalias has a bug.  The standard doesn't specify the
virtual-machine semantics of broken programs, only correct programs.

Barry Margolin
Thinking Machines Corp.

barmar@think.com
uunet!think!barmar

flaps@dgp.toronto.edu (Alan J Rosenthal) (01/08/88)

Let's be careful not to turn this into a flame war, please, but in a recent
article ok@quintus.UUCP (Richard A. O'Keefe) writes:

>Passing #pragmas through to the compiler means that
>(1) /lib/cpp	has to parse stuff which is significant to the C
>		compiler, and ONLY to the C compiler.

Not 'parse', just 'accept lines beginning with'.  cpp already must
include code for taking the first token of a '#' line to see if it is
'if', 'include', etc.  All it has to do is
    if(strcmp(token,"pragma") == 0)
	printf("%s\n",line);

...

>#line is a different case...
>In fact, as your example shows, the main function of # <lino> <file>
>is not to be passed through by the preprocessor, but to be generated
>by the preprocessor.  I have never written a # <lino> <file> in my
>life, but the preprocessor has made millions for me ...

Ahem, no human writes # <line> <file> lines, but plenty of programs
which come before cpp do, such as yacc and lex.  (In fact, this is the
K&R documented use for this feature.)

...

>One of the things one wants to do with a program is to analyse it...

>The easiest way to hack this is
>	cc -E source.c | analyser
>which means that your analyser doesn't have to be a preprocessor as
>well as a parser!  The # <line> <file> lines generated by the
>preprocessor tell you ... where things came from...
>
>If the "pragma" construct is defined as pragma(..) in the compiler
>language, then each tool has to be prepared to skip a parenthesis
>balanced sequence of tokens after pragma() but can otherwise ignore
>the construct.  But if #pragma is a pass-through (as some quite
>undocumented form) then I can't defend my tool against it, because
>I don't know what the passed-through form is going to look like.

But even better, if you write your cpp to take an option which causes
it to eat pragmas, or to object to them, either of which (or both)
would be easy to implement, it's even easier.  The ANSI committee can't
specify this any more than they can specify the existence of cpp or
cc -E, but I would hope that good cpp writers would implement it.

In any case, your "as some quite undocumented form" misses the point.
The documentation of this form is part of the documentation for the
(not necessarily existing) cpp, not for the C standard.

ajr
-- 
"Bill Joy uses EMACS."  - D. Hugh Redelmeier

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/08/88)

In article <14460@think.UUCP> barmar@sauron.think.com.UUCP (Barry Margolin) writes:
>Any program
>tha behaves differently depending on whether a variable was declared
>with noalias has a bug.

Yes, but my point was that is not true if you replace "noalias" with
"pragma".  It must behave the same (so far as the virtual machine is
concerned) regardless of the pragma.  Therefore no pragma can replace
"noalias", since I've shown that some code can be rendered "buggy"
simply by adding "noalias" at the [in]appropriate spots.  This is a
demonstration of the point, not a recommended practice!

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/08/88)

In article <1797@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>The point being that semantically equivalent virtual machines could
>still be remarkably different in speed and memory capabilities.

Well, yes, but I would expect that since the software presumably passed
testing, it would be adequate.  Nothing unexpected should sudden crop up
at run time that wouldn't also be a problem for things besides pragmas.
(If this occurred, it would indicate that some section of the code had
not been adequately tested.)

Besides, those missiles will be using Ada anyway, so the DoD says.
What a joke.

msf@amelia.nas.nasa.gov (Michael S. Fischbein) (01/08/88)

In article <6985@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>Besides, those missiles will be using Ada anyway, so the DoD says.
>What a joke.

Yes, Doug, it's very Jovial.
		mike


-- 
Michael Fischbein                 msf@prandtl.nas.nasa.gov
                                  ...!seismo!decuac!csmunix!icase!msf
These are my opinions and not necessarily official views of any
organization.

nevin1@ihlpf.ATT.COM (00704A-Liber) (01/09/88)

In article <14460@think.UUCP> barmar@sauron.think.com.UUCP (Barry Margolin) writes:
>[some stuff deleted].  Any program
>that behaves differently depending on whether a variable was declared
>with noalias has a bug.  The standard doesn't specify the
>virtual-machine semantics of broken programs, only correct programs.

I agree.  However, suppose I compile a program that uses 'noalias' with a
compiler that ignores 'noalias'.  I test it and find no problems.  I now have a
program which I believe works but if ported to a compiler which uses 'noalias'
it might develop a bug.

I believe that all programs which will conform to the ANSI C standard should
run equivalently under all compilers that conform to ANSI C.  (I do not believe
that ANSI requires a compiler writer to implement the optimizations that can be
made with the use of noalias.)  With noalias, this cannot be assured.
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

chris@mimsy.UUCP (Chris Torek) (01/09/88)

[Now this is odd.  I, who am quite opposed to noalias, find myself
shooting at an argument against it:]

In article <3313@ihlpf.ATT.COM> nevin1@ihlpf.ATT.COM (00704A-Liber) writes:
>... suppose I compile a program that uses 'noalias' with a compiler that
>ignores 'noalias'.  I test it and find no problems.  I now have a program
>which I believe works but if ported to a compiler which uses 'noalias'
>it might develop a bug.

Unfortunately, this argument (which I myself used, after a fashion)
fails in general, for there are any number of things you can do to
produce code that, while incorrect, still works on some particular
architecture.

I think the two best arguments against noalias are 0) it is late
to be adding keywords and 1) it does little for a good compiler.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 ????)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/09/88)

In article <10110@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>I think the two best arguments against noalias are 0) it is late
>to be adding keywords and 1) it does little for a good compiler.

0) I think the fact that "noalias" appeared as a keyword came as a
shock, which helps explain some of the initial reaction against it.
However, supposing that it really did address a serious need (which
is a matter of opinion), another type qualifier is clearly the best
way to add the capability.

1) To the contrary, I think "noalias" will always be ignored by a
poor compiler but will be exploited to the max by a good one.  It
allows use of vector instructions under some common circumstances,
for example.

barmar@think.COM (Barry Margolin) (01/12/88)

In article <3313@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704A-Liber,N.) writes:
>I agree.  However, suppose I compile a program that uses 'noalias' with a
>compiler that ignores 'noalias'.  I test it and find no problems.  I now have a
>program which I believe works but if ported to a compiler which uses 'noalias'
>it might develop a bug.

Suppose I compile a program that uses 36-bit numbers on a machine with
36-bit words.  I test it and find no problems.  I now have a program
which I believe works but if ported to a machine with 32-bit words it
might develop a bug.

>I believe that all programs which will conform to the ANSI C standard should
>run equivalently under all compilers that conform to ANSI C.  (I do not believe
>that ANSI requires a compiler writer to implement the optimizations that can be
>made with the use of noalias.)  With noalias, this cannot be assured.

A program which declares a variable as 'noalias' and then makes use of
multiple handles to the variable in such a way that it matters whether
'noalias' is recognized does not "conform to the ANSI C standard", so
you shouldn't expect it to run equivalently.  You can't expect an
invalid program to exhibit the same bug in all implementations,
because the standard only specifies the behavior of valid programs.

Barry Margolin
Thinking Machines Corp.

barmar@think.com
uunet!think!barmar

nevin1@ihlpf.ATT.COM (00704A-Liber) (01/12/88)

In article <10110@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>In article <3313@ihlpf.ATT.COM> nevin1@ihlpf.ATT.COM (00704A-Liber) writes:
>>... suppose I compile a program that uses 'noalias' with a compiler that
>>ignores 'noalias'.  I test it and find no problems.  I now have a program
>>which I believe works but if ported to a compiler which uses 'noalias'
>>it might develop a bug.
>
>Unfortunately, this argument (which I myself used, after a fashion)
>fails in general, for there are any number of things you can do to
>produce code that, while incorrect, still works on some particular
>architecture.

Here is an situation where the same architecture is used:

While I'm developing code, I don't turn the optimizing option of my compiler
on.  I test it and find no problems.  I then turn the optimizer on.  Now I find
problems.  (And will a debugger such as sdb be able to support 'noalias' so
that I can find the bugs in my optimized code?)

In order to make sure I have ANSI (so-called :-)) C compatibility, I MUST TEST
optimized code (optimized with respect to noalias, that is).

>>I believe that all programs which will conform to the ANSI C standard should
>>run equivalently under all compilers that conform to ANSI C.  (I do not
>>believe that ANSI requires a compiler writer to implement the optimizations
>>that can be made with the use of noalias.)  With noalias, this cannot be
>>assured.

I still believe this.  (BTW, although I am against honoring parens, my argument
works FOR adding it to the language.)
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

franka@mmintl.UUCP (Frank Adams) (01/14/88)

In article <3313@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704A-Liber,N.) writes:
>I believe that all programs which will conform to the ANSI C standard
>should run equivalently under all compilers that conform to ANSI C.  With
>noalias, this cannot be assured.

Not a chance in the world!

If someone writes a program which assumes 32 bit ints, it will run
(correctly) on some machines with some compilers, and not on other machines
with other compilers.  This is exactly like writing a program which uses the
noalias keyword incorrectly.

All *correct* conforming programs should run equivalently under all
conforming compilers.  But there is always the possibility of an undetected
incorrectness.
-- 

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Ashton-Tate          52 Oakland Ave North         E. Hartford, CT 06108

hydrovax@nmtsun.nmt.edu (M. Warner Losh) (01/14/88)

In article <3333@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704A-Liber) writes:
>While I'm developing code, I don't turn the optimizing option of my compiler
>on.  I test it and find no problems.  I then turn the optimizer on.  Now I
>find problems.  (And will a debugger such as sdb be able to support 
>'noalias' so that I can find the bugs in my optimized code?)

   The whole purpose of optimization should be to produce equvalent programs
that execute either faster, or with less memory requirements.  The
noalias stuff sounds like it is agains the spirit of such an endevor,
because if used incorrectly, can cause bugs.  Hard to find bugs at that.
Overuse of the "register" class of variables doesn't break programs when
it is added (unless you happen to have a brain dead optimizer :-))  The
noalias stuff, however, can cause bugs that are a real b**** to find,
since ALMOST ALL DEBUGGERS don't support OPTIMIZED code, if the optimization
is reaaly extensive.  Having just finished a compiler's course, I know
that many optimization techniques lead to code that in no way resembles
the original code.  There are ways around these problems, however, since
if you are VERY VERY careful about how you traverse your data structures,
you can avoid MOST (but not all) of these bitfalls.

   Noalias, from a compiler writer's point of view, would be a wonderful
boon.  You could now make assumptions about when varaibles change (or
don't change) more easily than you could before.  I'm not sure that
these few advantages (in terms of a couple of instructions saved) would
be worth the pain it would put the USER of the compiler through when
he misuses this feature.

  I'm not necessarily talking about the initial writing of the
code.Most people who would use the noalias feature would know what is
going on.  The real problem occurs in the maintance cycle of the
program's life.  Most of the software gets maintained by the less
experienced, less knowladgeable programmers (especially after the
person who originally wrote it leaves the company).  These programmers
more than likely might make a fix that aliased somehting that was
declared as noalias (maybe a global in a .h file where the definition
is "hidden" from them.  Hidden in the sence that the definition is
not staring them in the face every time they pop into the editor to
work on the module.

   This feature, in my option, would be a dangerous one to have around.
If you need to produce highly optimized code for a small program
(<10k lines), then this would be great.  If you need to maintain a
large program (>1M lines), then noalias would lead to lots of time lost
to finding obscure bugs in only the OPTIMIZED version of the code.  In
fact, many people might just turn off all optimization when they discover
bugs like this, thus defeating the whole purpose of the noalias modifier
in the first place.

   One last note : the amount of existing code that this feature break
is probably very small.  I too would like to see some hard data to
support this claim.  And sorry to have rambled for so long.

-- 
bitnet:	lush@nmt.csnet			M. Warner Losh
csnet:	warner%hydrovax@nmtsun
uucp:	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!warner%hydrovax
	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!hydrovax
Warning:  Hydrovax is both a machine, and an account, so be careful.

chris@mimsy.UUCP (Chris Torek) (01/19/88)

In article <1227@nmtsun.nmt.edu> hydrovax@nmtsun.nmt.edu (M. Warner
Losh) writes:
>... many optimization techniques lead to code that in no way resembles
>the original code.

(There is some interesting research on debugging optimised code, by
leaving enough information for the debugger to `undo' optimisations
when showing state.  [Just wanted to mention it.])

>  Noalias, from a compiler writer's point of view, would be a wonderful
>boon. ... The real problem occurs in the maintance cycle of the
>program's life.

This is the most basic reason I oppose `noalias', although I believe
there are any number of other good reasons for it not to be in the
C standard.  (On the other hand, I also believe prototypes should not
be in the standard, so what does that prove...?)  The compiler writer
could receive a yet greater boon by having all those annoying *users*
write assembly code instead.  Where do you draw the line?  I think
it should be with `noalias' outside the standard.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

chip@ateng.UUCP (Chip Salzenberg) (01/22/88)

In article <1227@nmtsun.nmt.edu> hydrovax@nmtsun.nmt.edu (M. Warner Losh) writes:
>The noalias stuff sounds like it is agains the spirit of such an endevor,
>because if used incorrectly, can cause bugs.

Cars, when used incorrectly, kill people.  You want to give up driving?
-- 
Chip Salzenberg                 UUCP: "{codas,uunet}!ateng!chip"
A T Engineering                 My employer's opinions are a trade secret.
       "Anything that works is better than anything that doesn't."