Subject: Re: function call conventions From: Erik Naggum <erik@naggum.no> Date: 1996/04/26 Newsgroups: comp.lang.lisp Message-ID: <3039470963102521@arcana.naggum.no> [Sean Foderaro] | >> the real question: is it possible to assume in the caller that what | >> is known at its compile-time about the function's lambda list will | >> not change, provided that the function to be called is not declared | >> `notinline'? | | No, you can't make that assumption. The function's lambda list may be | different by the time you get around to calling it. (thanks also to David Gadbois for his reply.) I was unclear. I was thinking about complete type declarations, not just function definitions, but since I have been working with type inference systems to produce such declarations automatically, I didn't mention them explicitly. suppose you have a function definition (defun fun (foo &optional (bar 0) &key (zot 0) (quux #C(0d0 0d0))) ... (1+ bar)) and the compiler is able to infer the types so that the declaration (here largely meaningless -- a real example would be too large) (declare (string foo) (fixnum bar) (integer zot) ((complex double-float) quux)) would apply to the lambda list, and the declaration that would apply to function calls would go (declaim (ftype (function (string &optional fixnum &key (zot integer) (quux (complex double-float))) integer) fun)) given this, and the lack of a `notinline' declaration, I would like to believe that the compiler can, indeed, utilize this information in making the most out of the function call. dpANS CL (I believe the last public draft is practically the same as the published standard), says that a declamation of a function's type makes a function call (fun "foo" 9 :zot 42 :quux #C(23d0 1d0)) will be treated as if it were (the integer (fun (the string "foo") (the fixnum 9) :zot (the integer 42) :quux (the (complex double-float) #C(23d0 1d0))) I'm a little disappointed by the sheer amount of manual work involved in declaring these types, but, hey, that's what programmable programming languages are for, and I would never have worried about this if I weren't working with type inference systems. now I can clarify the question: provided that the function is not declared `notinline', can I do a heavily optimized function call utilizing this knowledge to make short-cuts, or would I still have to do the general case? that is, I infer from my readings of the standard and CLtL2 that the amount of optimization available to the compiler in function calls is limited with the `notinline' declaration, and expanded with the `inline' declaration. or, put another way, I think I understand the standard to mean that if I want to be able to redefine functions, I should declare them `notinline'. if I don't declare them `notinline', the compiler is free to make any number of assumptions from its visible definition of those functions, where "definition" _includes_ declarations of their calling patterns (ftype declarations). (the standard does not say this outright, I wonder if I can make that assumption.) now, IF these assumptions hold, I can reduce the function call overhead in Common Lisp to that of the SPARC function call convention, for instance, just like compilers for other languages do (I think these are called "ABI"). in other words, I should be able to compile a Common Lisp function and calls to it into "normal" function call conventions without very peculiar calling conventions (as far as other languages see them). the purpose of this elaborated question is to find out whether I can write a system for calling functions in any number of languages from Common Lisp through predefined calling conventions, and vice versa. this is not only a question of foreign function interfaces, but also of being able to write in Common Lisp and generate, e.g., C code that conforms to the C function calling conventions. using the extremely flexible lambda lists in Common Lisp, I think I should be able to map over the set of calling conventions in other languages and thus I can compute the complexity of the lambda lists that can communicate with individual languages. instead of using an approach like ILU, I would like to "compile" (translate, really), restricted sets of Common Lisp code into languages whose calling conventions I know. by extension, I expect to be able to write arbitrarily complex "calling conventions" that include protecting variables from GC and calling functions with variant calling conventions, such as in GNU Emacs, without enforcing these conventions on the caller. rather, the callee should specify its relationship to the external world through an interface specification, and then callers would comply. however, all this hinges on being able to write code in Common Lisp that retains its ability to compile and run in a Common Lisp system with all the bells and whistles present. I'm currently at the stage where I try to find out whether this is outright lunacy or just a hell of a lot of work. -- reinvention is its own reward