ARM systems come with two calling conventions: hard-float and soft-float. These calling conventions are binary incompatible, and operating systems are either hard-float or soft-float. Currently, Android and iOS are both soft-float, while Linux distributions are in the process of migration to hard-float: old distributions are soft-float and new distributions are hard-float.
When LispWorks compiles foreign interface (callers or callables), by default it generates "bi-compatible" code that can interface with either hard-float and soft-float foreign code. At run-time, the code checks an internal flag and uses the appropriate convention. The internal flag is set to the correct value on startup. The bi-compatible code is needed only for functions that pass or return float
values (including small structures containing float
values). Functions that pass and return only pointers and types like :int do not need it.
The bi-compatible code adds some overhead, both in size and speed, but this overhead is small and normally would not make a significant difference. You can tell the system to compile for only one calling convention, by passing the keyword argument :calling-convention
with the value :soft-float
or :hard-float
to the definers (define-foreign-function, define-foreign-callable and define-foreign-funcallable). This will result in slightly smaller code which is slightly faster, but will run only on one calling convention.
A special case is variadic functions (for example printf
), because these always uses the soft-float calling convention, even in hard-float binaries. Currently LispWorks does not have a way of recognizing a variadic function. This means that if you define a caller to such function (by define-foreign-function or use it in a call to define-foreign-callable) which take float
s, it will do the wrong thing on a hard-float system. Thus when you define such call you need to tell LispWorks to use soft-float calling convention. For example, defining a call to printf
which, apart from the string, takes a single argument which is a double
:
(fli:define-foreign-function (printf-with-a-double "printf")
((string (:reference-pass :ef-mb-string))
(double-arg :double-float))
:calling-convention :soft-float)
Because of the bi-compatible code, LispWorks binaries (fasl files) are compatible with both hard-float and soft-float. The Lisp heap is also compatible with both conventions. However, the executable (including LispWorks as a dynamic library) has also a small C program which starts it (the "xstarter"), and that is either hard-float or soft-float.
Therefore a LispWorks executable can run only on one calling convention, but the code that it compiles can run on both (strictly speaking, the executable actually runs, but does not work properly).
In particular, that means that it is possible to compile and build for Android and iOS on either soft-float or hard-float systems, because the delivery process uses the appropriate "xstarter" for the target operating system.
The fact that operating systems are of one calling convention is not necessarily permanent, because in principle the same operating system, and even the same process, can use different calling conventions with different functions. For example, Android now allows compiling some code using hard-float. Thus in the future there may be cases when some libraries will use a different calling convention from the operating system. In this case the interface to this library will have to be compiled explicitly with the correct calling convention.
LispWorks Foreign Language Interface User Guide and Reference Manual - 16 Feb 2015