From ...
From: Erik Naggum
Subject: Re: function call conventions
Date: 1996/04/26
Message-ID: <3039470963102521@arcana.naggum.no>
X-Deja-AN: 151472995
references: <3039432101496639@arcana.naggum.no>
organization: Naggum Software; +47 2295 0313
newsgroups: comp.lang.lisp
[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