golde@uw-beaver (Helmut Golde) (07/11/86)
. What do people think about allowing compilers to have their own compiler/machine specific operators, in a standardized format. I think it might be very useful to allow a compiler to have a non-portable operator to do something that might be very efficient in machine code, but is not provided for by C. I propose that the standardized format $op-name$ be used for these operators. I realize that these would be inherently unportable, but sometimes you *KNOW* what you are doing will never be ported and you don't want to switch to assembler or write a vert inefficient function. A couple of examples follow: 1. More bit-manipulation routines, such as: a $rol$ b ::= rotate a left b bits a $ror$ b ::= rotate a right b bits a $bit$ b ::= value of b'th bit of a These would of course be usable as part of an assignment operator such as: a $rol$= 5; /* rotate a left 5 bits */ These instructions are provided by MANY processors and are a pain to emulate in C. 2. Fast string/buffer routines. Some processors provide a very fast instruction(s) for copying data from one address to another. Providing built-in ternary operators for this would be convenient in some cases: d $copy$ s : n ::= given that s and d are both <type> pointers, copies n <type>s from s to d. (produces the value d) one could then write #define memcpy(d,s,n) ((d) $copy$ (s) : (n)) and #define strcpy(d,s) ((d) $copy$ (s) : strlen(s)+1) etc. 3. Built in math functions If the processor has more than the standard +,-,/,* operators (esp. for floating point), it would be more efficient to have built it operators that to perform function calls. Things like: $pow$, $sin$, $exp$, $log$, $atan$, etc. #define's could make these quite portable without sacrificing the speed advantage. Well, what think you? Worth it or not? ----------------------------- Peter Golde
ark@alice.UUCP (07/12/86)
> What do people think about allowing compilers to have their own > compiler/machine specific operators, in a standardized format. I think > it might be very useful to allow a compiler to have a non-portable operator > to do something that might be very efficient in machine code, but is not > provided for by C. > I propose that the standardized format $op-name$ be used for these operators. C already has a hook for such things. It's called the "asm" statement. Despite its name, there is no law that says that what follows "asm" must in fact be assembly language. If you're writing the compiler, you can implement whatever syntax you like with whatever semantics you like.
chris@umcp-cs.UUCP (07/12/86)
In article <1825@uw-beaver> golde@uw-beaver.UUCP (Helmut Golde) writes: >What do people think about allowing compilers to have their own >compiler/machine specific operators, in a standardized format. The current ANSI C draft standard (or at least the last one I saw) allows this in a different way, which I will explain later. >I propose that the standardized format $op-name$ be used for these >operators. > >I realize that these would be inherently unportable, but sometimes you >*KNOW* what you are doing will never be ported and you don't want to >switch to assembler or write a vert inefficient function. > >A couple of examples follow: > >1. More bit-manipulation routines, such as: > a $rol$ b ::= rotate a left b bits > a $ror$ b ::= rotate a right b bits > a $bit$ b ::= value of b'th bit of a (The last example is perhaps not so good: (a & (1 << b)) is both equivalent and portable.) >These would of course be usable as part of an assignment operator such as: > >a $rol$= 5; /* rotate a left 5 bits */ This is not provided in ANSI C, as we shall soon `C'. (Sorry) >These instructions are provided by MANY processors and are a pain to >emulate in C. > >2. Fast string/buffer routines. [memory copy, fill, etc.] >3. Built in math functions An ANSI-conforming C compiler can implement memcpy(), log(), sin(), etc. inline by `tricky' use of `define's. This could be extended to functions like `rol(a, b)'. Here is an example of how this may be implemented: /* extract from <math.h> */ double sin(double x); /* declare the real function */ double _builtin_sin(double x); /* and the compiler version */ #define sin(x) _builtin_sin(x) /* default to the compiler version */ /* extract from user file */ #include <math.h> ... y = sin(x); ... which of course expands to y = _builtin_sin(x); and the compiler is free to handle this as it wishes. The draft standard emphasises that #undef sin guarantees that a function call, not an inline expansion, will be used. Note that this has some, er, `interesting' implications: #include <math.h> double subr(double (*fp)(double arg)) { return ((fp)(3.1415926535897932384626433832795));/* approx */ } strange() { ... subr(sin) ... /* NOW what? */ } This seems to call subr(_builtin_sin). The draft standard says that because `sin' appears here without a following `(', it is not macro- expanded; thus this in fact passes the address of the library function. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
gwyn@BRL.ARPA (07/12/86)
What most implementations that support such machine-specific operations do is have the compiler recognize apparent function names and generate the appropriate machine-specific code instead of a function call. E.g. _rol( a, b ); /* generates code to rotate a left b bits */ This approach has the advantage of fitting into the existing language syntax, so that other tools for dealing with C (lint, ctrace, cxref, cpp, etc.) aren't affected.
peters@cubsvax.UUCP (07/12/86)
In article <uw-beave.1825> golde@uw-beaver.UUCP (Helmut Golde) writes: >3. Built in math functions > >If the processor has more than the standard +,-,/,* operators (esp. for >floating point), it would be more efficient to have built it operators >that to perform function calls. Things like: > >$pow$, $sin$, $exp$, $log$, $atan$, etc. > >#define's could make these quite portable without sacrificing the speed >advantage. What does the draft standard say about things that look like function calls actually being implemented otherwise? Things a la FORTRAN's intrinsic functions: when I write y=SQRT(x) in FORTRAN, this looks just like any other function call, but even UNIX's f77 doesn't generate a function call (I believe), though as far as I know there's nothing in the FORTRAN77 standard to preclude this. (Then again, I don't know much about the F77 standard.) Unless there are good reasons not to do this, a given implementation of C on some machine could actually implement log(x) without a function call -- by an instruction to a special-purpose processor, or even by software generated by the compiler that runs on the cpu. This would preclude the need for any #defines. Regardless of what the draft standard might say, what do the net guru's feel about this? Even if it turns out to be a bad idea, there ought to be a more system- independent way than #defines of specifying things -- like a compile-time option to perform math library "functions calls" by some other means, if the other means exist . This option need only exist on the machines where the other means exist.... The use of #defines means either that the writer has to worry about such exigencies when he's developing the code, or else that the porter (not in the railroad-terminal sense!) has to worry about going into the code and adding lines. Peter S. Shenkin Columbia Univ. Biology Dept., NY, NY 10027 {philabs,rna}!cubsvax!peters cubsvax!peters@columbia.ARPA
roy@phri.UUCP (07/12/86)
In article <1825@uw-beaver> golde@uw-beaver.UUCP (Helmut Golde) writes: > What do people think about allowing compilers to have their own > compiler/machine specific operators, in a standardized format. [...] > a $rol$= 5; /* rotate a left 5 bits */ If you want to do that sort of stuff (gross, but admitedly sometimes worth the big efficiency win), what's wrong with the following? # ifdef MY_FAVORITE_CPU asm ("rol a, #5"); /* Use nifty built-in rotate left instruction */ # elseif a = rol_func (a); /* Don't have that instruction? do it in software */ # endif If you wanted to be cynical, you could always claim that we already do have exactly what you are talking about :-) a <<= 5; /* use nifty pdp-11 shift-left instruction */ b = *--p; /* use nifty pdp-11 auto-decrement mode */ -- Roy Smith, {allegra,philabs}!phri!roy System Administrator, Public Health Research Institute 455 First Avenue, New York, NY 10016
barmar@mit-eddie.UUCP (07/12/86)
Rather than inventing operators that are known to be unportable, why not write the operations as function calls, and teach compilers to open-code calls to certain functions. You would, of course, need compiler directives to override this, in case you are planning on linking the program with a different version of the library function. Fortran, PL/I, and Lisp compilers have been doing this for years. Just because something is written as a function call does not mean that it has to be implemented as one. -- Barry Margolin ARPA: barmar@MIT-Multics UUCP: ..!genrad!mit-eddie!barmar
brooks@lll-crg.UUCP (07/13/86)
>C already has a hook for such things. It's called the "asm" statement. >Despite its name, there is no law that says that what follows "asm" >must in fact be assembly language. If you're writing the compiler, >you can implement whatever syntax you like with whatever semantics you like. It would be nice if asm was more "printf like" instead of just dumping a string. I have made quite a lot of use of asms when writing things like multitasking packages and other things which need assembler hooks. Most of the code can be in C and be reasonably portable. I have often needed the ability to stick a stack address in an asm without knowing just what stack address you want to load... ie suppose you want to change the stack pointer... char *oldpointer; char *newpointer; asm("store sp,%a", oldpointer); asm("load sp,%a", newpointer); The code is machine dependent, but the compiler takes care of the C name -> AS name mapping for you. Of course I guess the compiler should not encourage such screwing around.
levy@ttrdc.UUCP (07/13/86)
In article <2364@umcp-cs.UUCP>, chris@umcp-cs.UUCP (Chris Torek) writes: > /* math.h */ > double _builtin_sin(double x); /* and the compiler version */ > #define sin(x) _builtin_sin(x) /* default to the compiler version */ >... >Note that this has some, er, `interesting' implications: > #include <math.h> > double > subr(double (*fp)(double arg)) { > > return ((fp)(3.1415926535897932384626433832795));/* approx */ > } > strange() { > > ... subr(sin) ... /* NOW what? */ > } >This seems to call subr(_builtin_sin). The draft standard says that >because `sin' appears here without a following `(', it is not macro- >expanded; thus this in fact passes the address of the library function. If so, this is a "new" feature at least compared with AT&T SysV (could someone check out BSD and others?) C compilers, which give an error message about "argument mismatch" if something like this is tried. Given that this is supposed to be a "standard," I wonder what C compilers support this now? I thought standards were supposed to, er, be codifications of a combination of the best features in existing compilers, not invent things out of the blue sky... (isn't this the way the Fortran 66 and 77 standardizations worked, for example?). Not that treating macros this way is a bad idea, I just would like to know who does it now. >In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) -- ------------------------------- Disclaimer: The views contained herein are | dan levy | yvel nad | my own and are not at all those of my em- | an engihacker @ | ployer or the administrator of any computer | at&t computer systems division | upon which I may hack. | skokie, illinois | -------------------------------- Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa, vax135}!ttrdc!ttrda!levy
peters@cubsvax.UUCP (07/14/86)
In article <mit-eddi.2526> barmar@mit-eddie.UUCP (Barry Margolin) writes: > ...why not >write the operations as function calls, and teach compilers to open-code >calls to certain functions. > >Fortran, PL/I, and Lisp compilers have been doing this for years. Just >because something is written as a function call does not mean that it >has to be implemented as one. Yes; I tried to send off a similar comment on the original posting, but it never made it off site. What I'd like to know is whether the draft standard permits this, and what the net guru's think about it. In Chris Torek's comment on the original posting, he proposes a workaround permitted by the draft ANSI, and notes that it is bug-prone. If this means that the draft standard doesn't permit "function calls" to be implemented otherwise, I'm curious what the objections are to this practice. Peter S. Shenkin Columbia Univ. Biology Dept., NY, NY 10027 {philabs,rna}!cubsvax!peters cubsvax!peters@columbia.ARPA
chris@umcp-cs.UUCP (07/15/86)
>In article <mit-eddi.2526> barmar@mit-eddie.UUCP (Barry Margolin) writes: >>...why not write the operations as function calls, and teach compilers >>to open-code calls to certain functions. In article <503@cubsvax.UUCP> peters@cubsvax.UUCP (Peter S. Shenkin) replies: >Yes; I tried to send off a similar comment on the original posting, but >it never made it off site. What I'd like to know is whether the draft >standard permits this, and what the net guru's think about it. > >In Chris Torek's comment on the original posting, he proposes a workaround >permitted by the draft ANSI, and notes that it is bug-prone. If this means >that the draft standard doesn't permit "function calls" to be implemented >otherwise, I'm curious what the objections are to this practice. Actually, the workaround comes off as being recommended by the draft standard, at least to me. I am not certain it is bug-prone, but it sure does `feel' odd. Apparently the committee (or a large faction thereof) is quite concerned about ensuring that there is some easy way to ensure a `real function call'. They want a standardised way of defeating in-line expansion, and have, at least for the nonce, settled upon `#undef funcname'. A `#pragma' seems to me to be at least as good an idea; compilers that never open-code a function call can ignore this, while those that might perform this optimisation could be required to pay attention to at least this one pragma. Then instead of #include <math.h> #undef sin /* make sure we get a function */ ... we might have #include <math.h> #pragma disable_inline(sin) /* get a function */ ... #pragma enable_inline(sin) /* back to possible inline */ ... #pragma disable_inline(sin) /* back to function */ This has the advantage of being reversible, as well. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
robert@cheviot.newcastle.ac.uk (Robert Stroud) (07/15/86)
In article <3519@lll-crg.ARpA> brooks@lll-crg.UUCP (Eugene D. Brooks III) writes: >It would be nice if asm was more "printf like" instead of just dumping >a string. >suppose you want to change the stack pointer... > > char *oldpointer; > char *newpointer; > > asm("store sp,%a", oldpointer); > asm("load sp,%a", newpointer); > >The code is machine dependent, but the compiler takes care of the >C name -> AS name mapping for you. Of course I guess the compiler >should not encourage such screwing around. A machine called the Orion made by a British company called High Level Hardware has something similar. It is based on a bit slice architecture and has been microcoded as a stack based C machine. Consequently, it is possible to interpret asm(opcode, expr, ...) as "push all the C expressions onto the stack and then perform opcode". This lets you mix C expressions with special-purpose opcodes (you can define your own because the microcode is user-extensible). However, the clean semantics are only possible because it is a stack machine and all operations are performed in this way. Robert Stroud, Computing Laboratory, University of Newcastle upon Tyne. ARPA robert%cheviot.newcastle@ucl-cs.ARPA UUCP ...!ukc!cheviot!robert JANET robert@newcastle.cheviot
peters@cubsvax.UUCP (07/15/86)
>>In article <mit-eddi.2526> barmar@mit-eddie.UUCP (Barry Margolin) writes: >>>...why not write the operations as function calls, and teach compilers >>>to open-code calls to certain functions. >In article <503@cubsvax.UUCP> peters@cubsvax.UUCP (Peter S. Shenkin) replies: >> ... What I'd like to know is whether the draft >>standard permits this, and what the net guru's think about it. In article <umcp-cs.2424> chris@maryland.UUCP (Chris Torek) writes: >Apparently the committee (or a large faction thereof) is quite >concerned about ensuring that there is some easy way to ensure a >`real function call'. Yes, apparently so, but WHY? What the hell difference does it make, from the user's point of view? That is, why should he ever be anything other than happy, if some alternative invoked by the compiler produces faster- running code? Peter S. Shenkin Columbia Univ. Biology Dept., NY, NY 10027 {philabs,rna}!cubsvax!peters cubsvax!peters@columbia.ARPA
tainter@ihlpg.UUCP (07/16/86)
> >In article <mit-eddi.2526> barmar@mit-eddie.UUCP (Barry Margolin) writes: > >>...why not write the operations as function calls, and teach compilers > >>to open-code calls to certain functions. > > In article <503@cubsvax.UUCP> peters@cubsvax.UUCP (Peter S. Shenkin) replies: > >Yes; I tried to send off a similar comment on the original posting, but > >it never made it off site. What I'd like to know is whether the draft > >standard permits this, and what the net guru's think about it. > > > >In Chris Torek's comment on the original posting, he proposes a workaround > >permitted by the draft ANSI, and notes that it is bug-prone. If this means > >that the draft standard doesn't permit "function calls" to be implemented > >otherwise, I'm curious what the objections are to this practice. > > Actually, the workaround comes off as being recommended by the > draft standard, at least to me. I am not certain it is bug-prone, > but it sure does `feel' odd. > > Apparently the committee (or a large faction thereof) is quite > concerned about ensuring that there is some easy way to ensure a > `real function call'. They want a standardised way of defeating > in-line expansion, and have, at least for the nonce, settled upon > `#undef funcname'. A `#pragma' seems to me to be at least as good > an idea; compilers that never open-code a function call can ignore > this, while those that might perform this optimisation could be > required to pay attention to at least this one pragma. Then instead > of > > #include <math.h> > #undef sin /* make sure we get a function */ > ... > > we might have > > #include <math.h> > #pragma disable_inline(sin) /* get a function */ > ... > #pragma enable_inline(sin) /* back to possible inline */ > ... > #pragma disable_inline(sin) /* back to function */ > > This has the advantage of being reversible, as well. > -- > In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) > UUCP: seismo!umcp-cs!chris > CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu Has anyoe proposed : #suspend alpha #restore alpha to allow temporary suspension of a macro. #undef would mean multiple defines to restore the macro, which could be a pain to maintain, or imposes some odd coding conventions --j.a.tainter
roy@phri.UUCP (07/16/86)
In article <505@cubsvax.UUCP> peters@cubsvax.UUCP (Peter S. Shenkin) writes: [Regarding compilers replacing calls to library routines with in-line code] > What the hell difference does it make, from the user's point of view? > That is, why should he ever be anything other than happy, if some > alternative invoked by the compiler produces faster-running code? What if you want to trap and/or trace subroutine calls for diagnostic or tuning purposes or you want to supply your own version of the library routine because it's faster, more accurate, or more featureful? -- Roy Smith, {allegra,philabs}!phri!roy System Administrator, Public Health Research Institute 455 First Avenue, New York, NY 10016
peters@cubsvax.UUCP (07/16/86)
In article <phri.2391> roy@phri.UUCP (Roy Smith) writes: >[Regarding compilers replacing calls to library routines with in-line code] > What if you want to trap and/or trace subroutine calls for >diagnostic or tuning purposes... Then you're no worse off than tracing or timing portions of your own in-line code. > ... or you want to supply your own version of the >library routine because it's faster, more accurate, or more featureful? Use a #define to a new name, or code in a new name (one of these is probably best), or disenable in-line expansion of code by means of a compile-time flag. (In one of my postings I suggested that such a flag be available, but it's probably not really necessary.) Another possibility: if the compiler knew about things like sin(x), then the -lm flag would not be necessary in programs that "call" it; thus specifying -lm could over-ride in-line expansion.... Peter S. Shenkin Columbia Univ. Biology Dept., NY, NY 10027 {philabs,rna}!cubsvax!peters cubsvax!peters@columbia.ARPA
purtill@petrus.UUCP (07/16/86)
In article <505@cubsvax.UUCP> cubsvax!peters (Peter S. Shenkin) writes: > In article <umcp-cs.2424> chris@maryland.UUCP (Chris Torek) writes: > >Apparently the committee (or a large faction thereof) is quite > >concerned about ensuring that there is some easy way to ensure a > >`real function call'. > Yes, apparently so, but WHY? What the hell difference does it make, from > the user's point of view? That is, why should he ever be anything other > than happy, if some alternative invoked by the compiler produces faster- > running code? > > Peter S. Shenkin Columbia Univ. Biology Dept., NY, NY 10027 > {philabs,rna}!cubsvax!peters cubsvax!peters@columbia.ARPA Ever heard of debugging? You might well want to set a trap at that function, or even replace it with a different version that is somehow useful, such as a version that prints out its arguments. mark purtill (201) 829-5127 ^.-.^ Arpa: purtill@bellcore.com 435 south st 2H-307 ((")) Uucp: ihnp4!bellcore!purtill morristown nj 07960
peters@cubsvax.UUCP (07/17/86)
In article <petrus.224> purtill@petrus.UUCP (Mark Purtill) writes: [re: reasons for not permitting a compiler to expand "function calls" in-line] >Ever heard of debugging? You might well want to set a trap at that >function, or even replace it with a different version that is somehow >useful, such as a version that prints out its arguments. If you want to set a trap, in-line expansion is no worse than having to deal with anything else in your code that doesn't call a function. If you want to replace the built-in function with a new version, either use a new name in-line, or else write a #define to a new name. Since most people don't have source code to the math library anyway, both of your suggestions would seem to be more useful for debugging the compiler or math library than for debugging user code that invokes them. Assuming one has a compiler that works, these features would seem to be of little use to the USER, as opposed to the compiler-writer. And I don't care about the compiler- writer! But I'd still like to hear someone on the committee confirm that this is disallowed (if, in fact, it is!), and comment on what went into the committee's decision to disallow it. Peter S. Shenkin Columbia Univ. Biology Dept., NY, NY 10027 {philabs,rna}!cubsvax!peters cubsvax!peters@columbia.ARPA
rbj@icst-cmr (Root Boy Jim) (07/18/86)
> In article <phri.2391> roy@phri.UUCP (Roy Smith) writes: > >[Regarding compilers replacing calls to library routines with in-line code] > > What if you want to trap and/or trace subroutine calls for > >diagnostic or tuning purposes... > > Then you're no worse off than tracing or timing portions of your own in-line > code. It's not that simple. If I want to know when and from where I was called, it would please me greatly to merely set ONE breakpoint, and not have to track down every single call, especially if I didn't have source. > > ... or you want to supply your own version of the > >library routine because it's faster, more accurate, or more featureful? > > Use a #define to a new name, or code in a new name (one of these is probably > best), or disenable in-line expansion of code by means of a compile-time flag. Again, lack of source may screw you. In addition, you now have to recompile everything instead of merely relinking to replace a library routine. While I probably willing to accept inline expansion of say, strcpy, pray that some of these bozo vendors don't put malloc in the same bag. Inline expansion should be optional and under control of the coder. I don't even care if the default is expansion, and you have to work to get a real function call. Evolution, not Revolution (see end quote) please. A compile flag is too broad. I may want some but not all expanded inline. > (In one of my postings I suggested that such a flag be available, but it's > probably not really necessary.) Another possibility: if the compiler knew > about things like sin(x), then the -lm flag would not be necessary in programs > that "call" it; thus specifying -lm could over-ride in-line expansion.... The -lm is a LOADER flag. The COMPILER may never see it, especially if each source is compiled separately via a makefile. Besides, how does it equate `sin()' with -lm? Look up every function in the archive? No thanks. > Peter S. Shenkin Columbia Univ. Biology Dept., NY, NY 10027 > {philabs,rna}!cubsvax!peters cubsvax!peters@columbia.ARPA (Root Boy) Jim Cottrell <rbj@icst-cmr.arpa> Don't hit me!! I'm in the Twilight Zone!!! ~"But if you go quoting phrases of Zippy, YOW! You ain't gonna make it with anyone anyhow"~
mouse@mcgill-vision.UUCP (der Mouse) (07/29/86)
[>>> and >>>> blather about coding some functions in-line] >> Apparently the committee (or a large faction thereof) is quite >> concerned about ensuring that there is some easy way to ensure a >> `real function call'. > Yes, apparently so, but WHY? What the hell difference does it make, > from the user's point of view? That is, why should he ever be > anything other than happy, if some alternative invoked by the > compiler produces faster-running code? Just when you thought a topic had been beaten to death.... There are many reasons. Maybe I have a function j and I don't realize that the compiler wants to try to in-line code Bessel functions. Maybe I want my own sin() and cos(), for example, perhaps all the calls to sin() and cos() should remember their arguments and compute the other function as a side effect to speed up the common case of sin(x) and cos(x) in succession (and I can't afford the time to rewrite my code to use sincos() or something similar). Maybe I want to do something with a pointer to the function (not that this prevents in-line coding of other uses). Maybe I am writing a game like phantasia, where a character has the attribute of sin, and I want to have a function sin() which has nothing to do with the sine function. Maybe I want to be able to set breakpoints on entry to sin(). Maybe I want to save text space badly enough to be willing to accept the performance disadvantage (ROMing the code maybe, you don't always want to optimize for speed). -- der Mouse USA: {ihnp4,decvax,akgua,utzoo,etc}!utcsri!mcgill-vision!mouse think!mosart!mcgill-vision!mouse Europe: mcvax!decvax!utcsri!mcgill-vision!mouse ARPAnet: utcsri!mcgill-vision!mouse@uw-beaver.arpa "Come with me a few minutes, mortal, and we shall talk." - Piers Anthony, Bearing an Hourglass