peterc@ecr.UUCP (Peter Curran) (01/29/85)
This is a discussion of a C semantics issue which I have not seen discussed on the net, or elsewhere. The original question was, "Is it OK to take the address of a >>static<< function, and pass it to a separately-compiled function?" Saying the answer is "no" appears to allow the compiler to take advantage of the fact to optimize the calling sequence when data flow analyses, or whatever, indicate that the full calling sequence is not required. Saying the answer is "yes" means that I don't have to declare the comparison function used deep inside an implementation of an abstract data type to be external, even though its only use is to pass its address to "qsort", and it shouldn't be visible to any of the users of the data type. These arguments can be presented in various other ways, which I will omit. This problem arose practically in Version 2.0 of the Venix system for the IBM PC/XT, in their kludge to support large programs. (The kludge is not Venturecom's fault - they have actually done a goood job of supporting large programs on a brain-damaged machine.) However, they require a special form of call for inter-segment calls, which they do not use for static calls, since they are guaranteed to remain within a single segment. This is of course only a special case of the optimizations which may be possible. In reality, the answer might have to be "yes", making the Venix code in error. The reason is that a function may invoke another function by address. That function may be a static function in the same module or an external function in a separate module - unless the compiler gets very tricky, it will have to use the full calling sequence. Therefore, optimization may only be permitted for functions which do not have their addresses taken. Regardless of your views on all this, if you are really trying to write portable C code, don't pass the addresses of static functions around.
ndiamond@watdaisy.UUCP (Norman Diamond) (01/30/85)
> The original question was, "Is it OK to take the address of a >>static<< > function, and pass it to a separately-compiled function?" > > This problem arose practically in Version 2.0 of the Venix system for the > IBM PC/XT ... they require a special form of call for inter-segment calls, > which they do not use for static calls, since they are guaranteed to remain > within a single segment. > > In reality, the answer might have to be "yes", making the Venix code in error. > The reason is that a function may invoke another function by address. I think that Venix is in error, for exactly this reason. They (and their customers) have not been the only Intel users to be burnt by this quirk, and C is not the only language in which this problem exists. If the address of the function is taken, anywhere in the source module, then the compiler should generate long calling sequences for the function. -- Norman Diamond UUCP: {decvax|utzoo|ihnp4|allegra|clyde}!watmath!watdaisy!ndiamond CSNET: ndiamond%watdaisy@waterloo.csnet ARPA: ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa "Opinions are those of the keyboard, and do not reflect on me or higher-ups."
mike@hcradm.UUCP (Mike Tilson) (01/31/85)
The legality of exporting the address of a static function (e.g. by passing a pointer to another routine in another compiled file) ought to be identical to the legality of exporting the address of a static data item -- if one is legal then the other should also be legal. I think this argues that the operation should be legal. Quite some time ago, HCR implemented a memory mapping scheme to expand the code address range of the smaller PDP-11 processors, similar to the later Venix version. In earlier versions, this kind of operation caused trouble. In our implementation we fixed the problem. We discovered that real programs used this feature. A typical use involved exporting an array of function pointers with each function being "static". This hid the function names, which weren't supposed to ever be called except via the pointer table. This seemed like a reasonable thing to do. I don't think it should be considered non-portable. / Mike Tilson / Human Computing Resources Corp.
kpmartin@watmath.UUCP (Kevin Martin) (02/08/85)
In article <360@ecr.UUCP> peterc@ecr.UUCP (Peter Curran) writes: >The original question was, "Is it OK to take the address of a >>static<< >function, and pass it to a separately-compiled function?" > >Saying the answer is "no" appears to allow the compiler to take advantage of >the fact to optimize the calling sequence... > >Saying the answer is "yes" means that I don't have to declare the comparison >function used deep inside an implementation of an abstract data type to be >external, even though its only use is to pass its address to "qsort", and it >shouldn't be visible to any of the users of the data type. Seems to me the correct answer is 'yes'. Any time you take the address of *any* function, you need to ensure that the function accepts the 'long' calling sequence, and that you generate a pointer that is usable anywhere. This doesn't stop you from generating a function with *both* a fast and slow entry (if your architecture and stack design allow it), and using the slow entry for generating the pointers for (possibly) external calls, but calling the quick entry entry when you call the function directly. Kevin Martin, UofW Software Development Group
jsdy@SEISMO.ARPA (02/25/85)
Suggestion to make this usable (people who don't understand or WANT to understand the 80*86 have my full understanding & envy, and may turn to the next message.): The problem seems to be that static functions, under VENIX, are compiled as local to the segment and therefore have a short return sequence rather than a long return sequence. Well, the '&' unop, when applied to a function, produces a pointer whose only use is as an object from which to make an indirect call. It need not be the exact address in memory of the routine (although debuggers prefer this GREAT- LY!). Further, a static can only be accessed within its own module (obviously). Well, let's say that all function-addresses must be long pointers, and that calls indirected from such pointers must ne long calls. Well, we can still have local static functions, if we think it's worth it. Just have, for each static whose address is taken in the module, a long-return (unnamed) function whose sole purpose is to copy the args back onto the stack and do a short-call to the static routine. 'Course, this will cause problems with varargs functions ... Maybe it would just be better to make all functions long-return functions. ;-Z .r .sig
ptw@encore.UUCP (P. Tucker Withington) (02/25/85)
>it's worth it. Just have, for each static whose address is taken in >the module, a long-return (unnamed) function whose sole purpose is >to copy the args back onto the stack and do a short-call to the static Since the static function by def'n can't be seen outside the module, why not have *it* be the "(unnamed)" function? Seems even debuggers could live with that. If they can live with inverted and non-inverted loops (did you use -O?) they should be able to deal with direct and "indirect" functions. Presumably a function declared static should be optimized for "local" use. Taking the & of it and passing it out of the module, while legal, is perhaps a bit perverse (although C++ might not agree with that). Or you could choose a different CPU. o.o --tucker ~
jsdy@hadron.UUCP (Joseph S. D. Yao) (03/13/85)
> >it's worth it. Just have, for each static whose address is taken in > >the module, a long-return (unnamed) function whose sole purpose is > >to copy the args back onto the stack and do a short-call to the static > ... [suggests, essentially, making statics long-return just like externs, > then doesn't like it] ... > Or you could choose a different CPU. I like that last choice best. The 80*86 architecture never made me happy. Unfortunately, right about now the best selling u-chip is the 80*86 family, judging from the number of implementations I've seen. Least expensive, first in the market (~), IBM-approved, etc. Don't flame me for those observations -- they're what is. ;-S Joe Yao hadron!jsdy@seismo.{ARPA,UUCP}