mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-01-25 05:51:55 -08:00
Merge branch 'cleanup-obsolete-dffi' into develop
This commit is contained in:
commit
bcc8b64104
14 changed files with 360 additions and 1146 deletions
60
doc/ffi.xmlf
60
doc/ffi.xmlf
|
|
@ -80,8 +80,13 @@
|
|||
a little piece of assembly code does the job of translating the lisp data
|
||||
into foreign objects, storing the arguments in the stack and in CPU
|
||||
registers, calling the function and converting back the output of the
|
||||
function to lisp.</para></listitem>
|
||||
function to lisp.</para>
|
||||
|
||||
<para>&ECL; for this purpose utilizes the library "A Portable Foreign
|
||||
Function Interface Library" commonly known as <ulink
|
||||
url="https://sourceware.org/libffi/">libffi</ulink>.</para></listitem>
|
||||
</varlistentry>
|
||||
<!-- XXX: describe also DLOPEN interface, it's the 3rd option (!) -->
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
|
|
@ -103,46 +108,19 @@
|
|||
|
||||
<para>On the other hand, the dynamic approach allows us to choose the
|
||||
libraries we load at any time, look for the functions and invoke them even
|
||||
from the toplevel, but it relies on unportable techniques and requires from
|
||||
us, the developers of &ECL;, to know very well both the assembly code of the
|
||||
machine &ECL; runs on and the calling conventions of that particular
|
||||
operating system.</para>
|
||||
from the toplevel, but it relies on unportable techniques and requires the
|
||||
developers to know very well both the assembly code of the machine the code
|
||||
runs on and the calling conventions of that particular operating system. For
|
||||
these reasons &ECL; doesn't maintain it's own implementation of the DFFI but
|
||||
rather relies on the third party library.</para>
|
||||
|
||||
<para>&ECL; currently supports the static method on all platforms, and the
|
||||
dynamical one a few of the most popular ones, shown in <xref
|
||||
linkend="table.dffi"/>. You can test if your copy of &ECL; was built with
|
||||
DFFI by inspecting whether the symbol <symbol>:DFFI</symbol> is present in
|
||||
the list from variable <symbol>*FEATURES*</symbol>.</para>
|
||||
dynamical one a wide range of the most popular ones, shown in <ulink
|
||||
url="https://sourceware.org/libffi/">libffi</ulink>. You can test if your
|
||||
copy of &ECL; was built with DFFI by inspecting whether the symbol
|
||||
<symbol>:DFFI</symbol> is present in the list from variable
|
||||
<symbol>*FEATURES*</symbol>.</para>
|
||||
|
||||
<table xml:id="table.dffi">
|
||||
<title>DFFI support</title>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Architecture</entry>
|
||||
<entry>Support</entry>
|
||||
<entry>Operating systems</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Intel x86 32 bits</entry>
|
||||
<entry>Complete</entry>
|
||||
<entry>Any with SysV ABI (Linux, BSD), Windows, OS X</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Intel x86 64 bits</entry>
|
||||
<entry>In progress</entry>
|
||||
<entry>SysV ABI</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>PowerPC 32 bits</entry>
|
||||
<entry>In progress</entry>
|
||||
<entry>OS X</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section xml:id="ext.ffi.objects">
|
||||
|
|
@ -170,7 +148,7 @@
|
|||
|
||||
<para>The most important component of the object is the memory region where
|
||||
data is stored. By default &ECL; assumes that the user will perform automatic
|
||||
managment of this memory, deleting the object when it is no longer
|
||||
management of this memory, deleting the object when it is no longer
|
||||
needed. The first reason is that this block may have been allocated by a
|
||||
foreign routine using <function>malloc()</function>, or
|
||||
<function>mmap()</function>, or statically, by referring to a C constant. The
|
||||
|
|
@ -219,7 +197,7 @@
|
|||
<listitem>
|
||||
<para>&ECL;'s own low level interface. Only to be used if &ECL; is your
|
||||
deployment platform. It features some powerful constructs that allow you to
|
||||
merge arbitrary C code with lisp (<xref linkend="ref.c-inline"/> and <xref
|
||||
mix arbitrary C code with lisp (<xref linkend="ref.c-inline"/> and <xref
|
||||
linkend="ref.clines"/>).</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
|
@ -305,7 +283,7 @@ Build and load this module with (compile-file "cffi.lsp" :load t)
|
|||
;;
|
||||
(let ((c-cos (cffi:foreign-funcall "cos" :double 1.0d0 :double)))
|
||||
(format t "~%Lisp cos:~t~d~%C cos:~t~d~%Difference:~t~d"
|
||||
(sin 1.0d0) c-sin (- (sin 1.0d0) c-sin)))
|
||||
(cos 1.0d0) c-cos (- (cos 1.0d0) c-cos)))
|
||||
</programlisting>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
332
doc/tmp/COPYING.GFDL.xml
Normal file
332
doc/tmp/COPYING.GFDL.xml
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
<![CDATA[
|
||||
GNU Free Documentation License
|
||||
Version 1.1, March 2000
|
||||
|
||||
Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
0. PREAMBLE
|
||||
|
||||
The purpose of this License is to make a manual, textbook, or other
|
||||
written document "free" in the sense of freedom: to assure everyone
|
||||
the effective freedom to copy and redistribute it, with or without
|
||||
modifying it, either commercially or noncommercially. Secondarily,
|
||||
this License preserves for the author and publisher a way to get
|
||||
credit for their work, while not being considered responsible for
|
||||
modifications made by others.
|
||||
|
||||
This License is a kind of "copyleft", which means that derivative
|
||||
works of the document must themselves be free in the same sense. It
|
||||
complements the GNU General Public License, which is a copyleft
|
||||
license designed for free software.
|
||||
|
||||
We have designed this License in order to use it for manuals for free
|
||||
software, because free software needs free documentation: a free
|
||||
program should come with manuals providing the same freedoms that the
|
||||
software does. But this License is not limited to software manuals;
|
||||
it can be used for any textual work, regardless of subject matter or
|
||||
whether it is published as a printed book. We recommend this License
|
||||
principally for works whose purpose is instruction or reference.
|
||||
|
||||
|
||||
1. APPLICABILITY AND DEFINITIONS
|
||||
|
||||
This License applies to any manual or other work that contains a
|
||||
notice placed by the copyright holder saying it can be distributed
|
||||
under the terms of this License. The "Document", below, refers to any
|
||||
such manual or work. Any member of the public is a licensee, and is
|
||||
addressed as "you".
|
||||
|
||||
A "Modified Version" of the Document means any work containing the
|
||||
Document or a portion of it, either copied verbatim, or with
|
||||
modifications and/or translated into another language.
|
||||
|
||||
A "Secondary Section" is a named appendix or a front-matter section of
|
||||
the Document that deals exclusively with the relationship of the
|
||||
publishers or authors of the Document to the Document's overall subject
|
||||
(or to related matters) and contains nothing that could fall directly
|
||||
within that overall subject. (For example, if the Document is in part a
|
||||
textbook of mathematics, a Secondary Section may not explain any
|
||||
mathematics.) The relationship could be a matter of historical
|
||||
connection with the subject or with related matters, or of legal,
|
||||
commercial, philosophical, ethical or political position regarding
|
||||
them.
|
||||
|
||||
The "Invariant Sections" are certain Secondary Sections whose titles
|
||||
are designated, as being those of Invariant Sections, in the notice
|
||||
that says that the Document is released under this License.
|
||||
|
||||
The "Cover Texts" are certain short passages of text that are listed,
|
||||
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
|
||||
the Document is released under this License.
|
||||
|
||||
A "Transparent" copy of the Document means a machine-readable copy,
|
||||
represented in a format whose specification is available to the
|
||||
general public, whose contents can be viewed and edited directly and
|
||||
straightforwardly with generic text editors or (for images composed of
|
||||
pixels) generic paint programs or (for drawings) some widely available
|
||||
drawing editor, and that is suitable for input to text formatters or
|
||||
for automatic translation to a variety of formats suitable for input
|
||||
to text formatters. A copy made in an otherwise Transparent file
|
||||
format whose markup has been designed to thwart or discourage
|
||||
subsequent modification by readers is not Transparent. A copy that is
|
||||
not "Transparent" is called "Opaque".
|
||||
|
||||
Examples of suitable formats for Transparent copies include plain
|
||||
ASCII without markup, Texinfo input format, LaTeX input format, SGML
|
||||
or XML using a publicly available DTD, and standard-conforming simple
|
||||
HTML designed for human modification. Opaque formats include
|
||||
PostScript, PDF, proprietary formats that can be read and edited only
|
||||
by proprietary word processors, SGML or XML for which the DTD and/or
|
||||
processing tools are not generally available, and the
|
||||
machine-generated HTML produced by some word processors for output
|
||||
purposes only.
|
||||
|
||||
The "Title Page" means, for a printed book, the title page itself,
|
||||
plus such following pages as are needed to hold, legibly, the material
|
||||
this License requires to appear in the title page. For works in
|
||||
formats which do not have any title page as such, "Title Page" means
|
||||
the text near the most prominent appearance of the work's title,
|
||||
preceding the beginning of the body of the text.
|
||||
|
||||
|
||||
2. VERBATIM COPYING
|
||||
|
||||
You may copy and distribute the Document in any medium, either
|
||||
commercially or noncommercially, provided that this License, the
|
||||
copyright notices, and the license notice saying this License applies
|
||||
to the Document are reproduced in all copies, and that you add no other
|
||||
conditions whatsoever to those of this License. You may not use
|
||||
technical measures to obstruct or control the reading or further
|
||||
copying of the copies you make or distribute. However, you may accept
|
||||
compensation in exchange for copies. If you distribute a large enough
|
||||
number of copies you must also follow the conditions in section 3.
|
||||
|
||||
You may also lend copies, under the same conditions stated above, and
|
||||
you may publicly display copies.
|
||||
|
||||
|
||||
3. COPYING IN QUANTITY
|
||||
|
||||
If you publish printed copies of the Document numbering more than 100,
|
||||
and the Document's license notice requires Cover Texts, you must enclose
|
||||
the copies in covers that carry, clearly and legibly, all these Cover
|
||||
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
|
||||
the back cover. Both covers must also clearly and legibly identify
|
||||
you as the publisher of these copies. The front cover must present
|
||||
the full title with all words of the title equally prominent and
|
||||
visible. You may add other material on the covers in addition.
|
||||
Copying with changes limited to the covers, as long as they preserve
|
||||
the title of the Document and satisfy these conditions, can be treated
|
||||
as verbatim copying in other respects.
|
||||
|
||||
If the required texts for either cover are too voluminous to fit
|
||||
legibly, you should put the first ones listed (as many as fit
|
||||
reasonably) on the actual cover, and continue the rest onto adjacent
|
||||
pages.
|
||||
|
||||
If you publish or distribute Opaque copies of the Document numbering
|
||||
more than 100, you must either include a machine-readable Transparent
|
||||
copy along with each Opaque copy, or state in or with each Opaque copy
|
||||
a publicly-accessible computer-network location containing a complete
|
||||
Transparent copy of the Document, free of added material, which the
|
||||
general network-using public has access to download anonymously at no
|
||||
charge using public-standard network protocols. If you use the latter
|
||||
option, you must take reasonably prudent steps, when you begin
|
||||
distribution of Opaque copies in quantity, to ensure that this
|
||||
Transparent copy will remain thus accessible at the stated location
|
||||
until at least one year after the last time you distribute an Opaque
|
||||
copy (directly or through your agents or retailers) of that edition to
|
||||
the public.
|
||||
|
||||
It is requested, but not required, that you contact the authors of the
|
||||
Document well before redistributing any large number of copies, to give
|
||||
them a chance to provide you with an updated version of the Document.
|
||||
|
||||
|
||||
4. MODIFICATIONS
|
||||
|
||||
You may copy and distribute a Modified Version of the Document under
|
||||
the conditions of sections 2 and 3 above, provided that you release
|
||||
the Modified Version under precisely this License, with the Modified
|
||||
Version filling the role of the Document, thus licensing distribution
|
||||
and modification of the Modified Version to whoever possesses a copy
|
||||
of it. In addition, you must do these things in the Modified Version:
|
||||
|
||||
A. Use in the Title Page (and on the covers, if any) a title distinct
|
||||
from that of the Document, and from those of previous versions
|
||||
(which should, if there were any, be listed in the History section
|
||||
of the Document). You may use the same title as a previous version
|
||||
if the original publisher of that version gives permission.
|
||||
B. List on the Title Page, as authors, one or more persons or entities
|
||||
responsible for authorship of the modifications in the Modified
|
||||
Version, together with at least five of the principal authors of the
|
||||
Document (all of its principal authors, if it has less than five).
|
||||
C. State on the Title page the name of the publisher of the
|
||||
Modified Version, as the publisher.
|
||||
D. Preserve all the copyright notices of the Document.
|
||||
E. Add an appropriate copyright notice for your modifications
|
||||
adjacent to the other copyright notices.
|
||||
F. Include, immediately after the copyright notices, a license notice
|
||||
giving the public permission to use the Modified Version under the
|
||||
terms of this License, in the form shown in the Addendum below.
|
||||
G. Preserve in that license notice the full lists of Invariant Sections
|
||||
and required Cover Texts given in the Document's license notice.
|
||||
H. Include an unaltered copy of this License.
|
||||
I. Preserve the section entitled "History", and its title, and add to
|
||||
it an item stating at least the title, year, new authors, and
|
||||
publisher of the Modified Version as given on the Title Page. If
|
||||
there is no section entitled "History" in the Document, create one
|
||||
stating the title, year, authors, and publisher of the Document as
|
||||
given on its Title Page, then add an item describing the Modified
|
||||
Version as stated in the previous sentence.
|
||||
J. Preserve the network location, if any, given in the Document for
|
||||
public access to a Transparent copy of the Document, and likewise
|
||||
the network locations given in the Document for previous versions
|
||||
it was based on. These may be placed in the "History" section.
|
||||
You may omit a network location for a work that was published at
|
||||
least four years before the Document itself, or if the original
|
||||
publisher of the version it refers to gives permission.
|
||||
K. In any section entitled "Acknowledgements" or "Dedications",
|
||||
preserve the section's title, and preserve in the section all the
|
||||
substance and tone of each of the contributor acknowledgements
|
||||
and/or dedications given therein.
|
||||
L. Preserve all the Invariant Sections of the Document,
|
||||
unaltered in their text and in their titles. Section numbers
|
||||
or the equivalent are not considered part of the section titles.
|
||||
M. Delete any section entitled "Endorsements". Such a section
|
||||
may not be included in the Modified Version.
|
||||
N. Do not retitle any existing section as "Endorsements"
|
||||
or to conflict in title with any Invariant Section.
|
||||
|
||||
If the Modified Version includes new front-matter sections or
|
||||
appendices that qualify as Secondary Sections and contain no material
|
||||
copied from the Document, you may at your option designate some or all
|
||||
of these sections as invariant. To do this, add their titles to the
|
||||
list of Invariant Sections in the Modified Version's license notice.
|
||||
These titles must be distinct from any other section titles.
|
||||
|
||||
You may add a section entitled "Endorsements", provided it contains
|
||||
nothing but endorsements of your Modified Version by various
|
||||
parties--for example, statements of peer review or that the text has
|
||||
been approved by an organization as the authoritative definition of a
|
||||
standard.
|
||||
|
||||
You may add a passage of up to five words as a Front-Cover Text, and a
|
||||
passage of up to 25 words as a Back-Cover Text, to the end of the list
|
||||
of Cover Texts in the Modified Version. Only one passage of
|
||||
Front-Cover Text and one of Back-Cover Text may be added by (or
|
||||
through arrangements made by) any one entity. If the Document already
|
||||
includes a cover text for the same cover, previously added by you or
|
||||
by arrangement made by the same entity you are acting on behalf of,
|
||||
you may not add another; but you may replace the old one, on explicit
|
||||
permission from the previous publisher that added the old one.
|
||||
|
||||
The author(s) and publisher(s) of the Document do not by this License
|
||||
give permission to use their names for publicity for or to assert or
|
||||
imply endorsement of any Modified Version.
|
||||
|
||||
|
||||
5. COMBINING DOCUMENTS
|
||||
|
||||
You may combine the Document with other documents released under this
|
||||
License, under the terms defined in section 4 above for modified
|
||||
versions, provided that you include in the combination all of the
|
||||
Invariant Sections of all of the original documents, unmodified, and
|
||||
list them all as Invariant Sections of your combined work in its
|
||||
license notice.
|
||||
|
||||
The combined work need only contain one copy of this License, and
|
||||
multiple identical Invariant Sections may be replaced with a single
|
||||
copy. If there are multiple Invariant Sections with the same name but
|
||||
different contents, make the title of each such section unique by
|
||||
adding at the end of it, in parentheses, the name of the original
|
||||
author or publisher of that section if known, or else a unique number.
|
||||
Make the same adjustment to the section titles in the list of
|
||||
Invariant Sections in the license notice of the combined work.
|
||||
|
||||
In the combination, you must combine any sections entitled "History"
|
||||
in the various original documents, forming one section entitled
|
||||
"History"; likewise combine any sections entitled "Acknowledgements",
|
||||
and any sections entitled "Dedications". You must delete all sections
|
||||
entitled "Endorsements."
|
||||
|
||||
|
||||
6. COLLECTIONS OF DOCUMENTS
|
||||
|
||||
You may make a collection consisting of the Document and other documents
|
||||
released under this License, and replace the individual copies of this
|
||||
License in the various documents with a single copy that is included in
|
||||
the collection, provided that you follow the rules of this License for
|
||||
verbatim copying of each of the documents in all other respects.
|
||||
|
||||
You may extract a single document from such a collection, and distribute
|
||||
it individually under this License, provided you insert a copy of this
|
||||
License into the extracted document, and follow this License in all
|
||||
other respects regarding verbatim copying of that document.
|
||||
|
||||
|
||||
7. AGGREGATION WITH INDEPENDENT WORKS
|
||||
|
||||
A compilation of the Document or its derivatives with other separate
|
||||
and independent documents or works, in or on a volume of a storage or
|
||||
distribution medium, does not as a whole count as a Modified Version
|
||||
of the Document, provided no compilation copyright is claimed for the
|
||||
compilation. Such a compilation is called an "aggregate", and this
|
||||
License does not apply to the other self-contained works thus compiled
|
||||
with the Document, on account of their being thus compiled, if they
|
||||
are not themselves derivative works of the Document.
|
||||
|
||||
If the Cover Text requirement of section 3 is applicable to these
|
||||
copies of the Document, then if the Document is less than one quarter
|
||||
of the entire aggregate, the Document's Cover Texts may be placed on
|
||||
covers that surround only the Document within the aggregate.
|
||||
Otherwise they must appear on covers around the whole aggregate.
|
||||
|
||||
|
||||
8. TRANSLATION
|
||||
|
||||
Translation is considered a kind of modification, so you may
|
||||
distribute translations of the Document under the terms of section 4.
|
||||
Replacing Invariant Sections with translations requires special
|
||||
permission from their copyright holders, but you may include
|
||||
translations of some or all Invariant Sections in addition to the
|
||||
original versions of these Invariant Sections. You may include a
|
||||
translation of this License provided that you also include the
|
||||
original English version of this License. In case of a disagreement
|
||||
between the translation and the original English version of this
|
||||
License, the original English version will prevail.
|
||||
|
||||
|
||||
9. TERMINATION
|
||||
|
||||
You may not copy, modify, sublicense, or distribute the Document except
|
||||
as expressly provided for under this License. Any other attempt to
|
||||
copy, modify, sublicense or distribute the Document is void, and will
|
||||
automatically terminate your rights under this License. However,
|
||||
parties who have received copies, or rights, from you under this
|
||||
License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
|
||||
10. FUTURE REVISIONS OF THIS LICENSE
|
||||
|
||||
The Free Software Foundation may publish new, revised versions
|
||||
of the GNU Free Documentation License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns. See
|
||||
http://www.gnu.org/copyleft/.
|
||||
|
||||
Each version of the License is given a distinguishing version number.
|
||||
If the Document specifies that a particular numbered version of this
|
||||
License "or any later version" applies to it, you have the option of
|
||||
following the terms and conditions either of that specified version or
|
||||
of any later version that has been published (not as a draft) by the
|
||||
Free Software Foundation. If the Document does not specify a version
|
||||
number of this License, you may choose any version ever published (not
|
||||
as a draft) by the Free Software Foundation.
|
||||
|
||||
]]>
|
||||
|
|
@ -96,16 +96,6 @@ apply_x86.c: $(srcdir)/arch/apply_x86.d $(DPP) $(HFILES)
|
|||
../CROSS-DPP $(srcdir)/arch/apply_x86.d $@ ; \
|
||||
else $(DPP) $(srcdir)/arch/apply_x86.d $@ ; \
|
||||
fi
|
||||
ffi_x86.c: $(srcdir)/arch/ffi_x86.d $(DPP) $(HFILES)
|
||||
if test -f ../CROSS-DPP ; then \
|
||||
../CROSS-DPP $(srcdir)/arch/ffi_x86.d $@ ; \
|
||||
else $(DPP) $(srcdir)/arch/ffi_x86.d $@ ; \
|
||||
fi
|
||||
ffi_x86_64.c: $(srcdir)/arch/ffi_x86_64.d $(DPP) $(HFILES)
|
||||
if test -f ../CROSS-DPP ; then \
|
||||
../CROSS-DPP $(srcdir)/arch/ffi_x86_64.d $@ ; \
|
||||
else $(DPP) $(srcdir)/arch/ffi_x86_64.d $@ ; \
|
||||
fi
|
||||
|
||||
../libeclmin.a: $(OBJS) all_symbols.o all_symbols2.o
|
||||
$(RM) $@
|
||||
|
|
|
|||
|
|
@ -1,215 +0,0 @@
|
|||
/* -*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*- */
|
||||
/* vim: set filetype=c tabstop=8 shiftwidth=4 expandtab: */
|
||||
|
||||
/*
|
||||
ffi_x86.c -- Nonportable component of the FFI
|
||||
*/
|
||||
/*
|
||||
Copyright (c) 2005, Juan Jose Garcia Ripoll.
|
||||
|
||||
ECL is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
See file '../Copyright' for full details.
|
||||
*/
|
||||
|
||||
#include <ecl/ecl.h>
|
||||
#include <string.h>
|
||||
#include <ecl/internal.h>
|
||||
|
||||
#error "This file is a placeholder for current development"
|
||||
|
||||
/*
|
||||
* Calling conventions for OS X under PowerPC/32bit architecture. The rules are
|
||||
* as follows:
|
||||
*
|
||||
* - Registers GPR3-GPR10 are used to pass 32-bit arguments. This includes
|
||||
* integers and composed data structures which fit in the registers.
|
||||
* - Registers FPR1-FPR13 are used to pass float and double arguments.
|
||||
* - For each argument passed in a register, the same amount of memory is
|
||||
* reserved in the stack.
|
||||
* - When the amount of registers is exhausted, the remaining arguments are
|
||||
* passed in the stack.
|
||||
* - There is a difference between functions whose signature is known and those
|
||||
* whose is not. In the second case, when passing float/double arguments,
|
||||
* they are passed redundantly using a GPR, a FPR and the stack. In the
|
||||
* former case, only the FPR or the stack is used.
|
||||
* - Since we do not allow functions with varargs (i.e "..." in C parlance), we
|
||||
* do not care about the last case.
|
||||
*
|
||||
* Since we do not allow passing or receiving structures, we need not care
|
||||
* about it and the only rule is:
|
||||
*
|
||||
* - Returns arguments <= 32 bits are stored in GPR3
|
||||
* - Returns arguments <= 64 bits are shared between GPR3 and GPR4, for high
|
||||
* and low bits, respectively.
|
||||
* - Floating point values are returned in FPR1.
|
||||
*
|
||||
* This information appears in "Mac OS X ABI Function Call Guide", from Apple
|
||||
* Developer's Documentation (April 2006).
|
||||
*/
|
||||
|
||||
#define MAX_INT_REGISTERS 8
|
||||
#define MAX_FP_REGISTERS 13
|
||||
|
||||
struct ecl_fficall_reg {
|
||||
long int registers[MAX_INT_REGISTERS];
|
||||
int int_registers_size;
|
||||
double fp_registers[MAX_FP_REGISTERS];
|
||||
int fp_registers_size;
|
||||
};
|
||||
|
||||
struct ecl_fficall_reg *
|
||||
ecl_fficall_prepare_extra(struct ecl_fficall_reg *registers)
|
||||
{
|
||||
if (registers == 0) {
|
||||
registers = (struct ecl_fficall_reg *)cl_alloc_atomic(sizeof(*registers));
|
||||
}
|
||||
registers->int_registers_size = 0;
|
||||
registers->fp_registers_size = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ecl_fficall_push_arg(union ecl_ffi_values *data, enum ecl_ffi_tag type)
|
||||
{
|
||||
long i;
|
||||
struct ecl_fficall *fficall = cl_env.fficall;
|
||||
struct ecl_fficall_reg *registers = cl_env.fficall->registers;
|
||||
switch (type) {
|
||||
case ECL_FFI_CHAR: i = data->c; goto INT;
|
||||
case ECL_FFI_UNSIGNED_CHAR: i = data->uc; goto INT;
|
||||
case ECL_FFI_BYTE: i = data->b; goto INT;
|
||||
case ECL_FFI_UNSIGNED_BYTE: i = data->ub; goto INT;
|
||||
case ECL_FFI_SHORT: i = data->s; goto INT;
|
||||
case ECL_FFI_UNSIGNED_SHORT: i = data->us; goto INT;
|
||||
case ECL_FFI_INT: i = data->i; goto INT;
|
||||
case ECL_FFI_UNSIGNED_INT: i = data->ui; goto INT;
|
||||
case ECL_FFI_LONG:
|
||||
case ECL_FFI_UNSIGNED_LONG:
|
||||
case ECL_FFI_POINTER_VOID:
|
||||
case ECL_FFI_CSTRING:
|
||||
case ECL_FFI_OBJECT:
|
||||
i = data->l;
|
||||
INT:
|
||||
if (registers->int_registers_size < MAX_INT_REGISTERS) {
|
||||
registers->registers[registers->int_registers_size++] = i;
|
||||
}
|
||||
ecl_fficall_align(sizeof(long));
|
||||
ecl_fficall_push_bytes(&i, sizeof(long));
|
||||
break;
|
||||
case ECL_FFI_DOUBLE:
|
||||
if (registers->fp_registers_size < MAX_FP_REGISTERS) {
|
||||
registers->fp_registers[registers->fp_registers_size++] = data->d;
|
||||
registers->int_registers_size += 2;
|
||||
}
|
||||
ecl_fficall_align(sizeof(long));
|
||||
ecl_fficall_push_bytes(&data->d, sizeof(double), sizeof(long));
|
||||
break;
|
||||
case ECL_FFI_FLOAT:
|
||||
if (registers->fp_registers_size < MAX_FP_REGISTERS) {
|
||||
registers->fp_registers[registers->fp_registers_size++] = data->f;
|
||||
registers->int_registers_size++;
|
||||
}
|
||||
ecl_fficall_align(sizeof(long));
|
||||
ecl_fficall_push_bytes(&data->f, sizeof(float), sizeof(long));
|
||||
break;
|
||||
case ECL_FFI_VOID:
|
||||
FEerror("VOID is not a valid argument type for a C function", 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ecl_fficall_do_execute(cl_index buf_size, void *stack, void *gpr, void *gpfr, void *f)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ecl_fficall_execute(void *_f_ptr, struct ecl_fficall *fficall, enum ecl_ffi_tag return_type)
|
||||
{
|
||||
struct ecl_fficall_reg *registers = fficall->registers;
|
||||
long bufsize = fficall->buffer_size;
|
||||
char* buf = fficall->buffer;
|
||||
|
||||
asm volatile (
|
||||
"mr r5,%[bufsize]\n\t" /* r5 = size of stack */
|
||||
"mr r6,%[buf]\n\t" /* r6 = origin of stack data */
|
||||
"mr r17,%[registers]\n\t" /* r17 = origin of integer registers */
|
||||
"mr r16,%[fp_registers]\n\t"/* r16 = origin of fp registers */
|
||||
"mr r15,%[fptr]\n\t" /* r15 = _f_ptr */
|
||||
"mr r29, r1\n\t" /* r29 saves r1 */
|
||||
|
||||
"subf r13,r5,r1\n\t"
|
||||
"stwu r13,-80(r13)\n\t" /* r13 <- r1 - r5 - 80 */
|
||||
"mflr r0\n\t"
|
||||
"stw r0,8(r1)\n\t"
|
||||
"mr r1,r13\n\t" /* r1 <- r13 */
|
||||
|
||||
"stwu r14,24(r1)\n\t" /* r14 <- begin of parameters */
|
||||
"cmpwi cr0,r5,0\n\t" /* copy r5 bytes from (r6) to (r14) */
|
||||
"ble cr0,L3\n\t"
|
||||
"mtctr r5\n"
|
||||
"LX: lbz r0,0(r6)\n\t"
|
||||
"addi r6,r6,1\n\t"
|
||||
"stb r0,0(r14)\n\t"
|
||||
"addi r14,r14,1\n"
|
||||
"L3: lfd f1, 0(r16)\n\t" /* load fp registers from (r16) */
|
||||
"lfd f2, 8(r16)\n\t"
|
||||
"lfd f3, 16(r16)\n\t"
|
||||
"lfd f4, 24(r16)\n\t"
|
||||
"lfd f5, 32(r16)\n\t"
|
||||
"lfd f6, 40(r16)\n\t"
|
||||
"lfd f7, 48(r16)\n\t"
|
||||
"lfd f8, 56(r16)\n\t"
|
||||
"lfd f9, 64(r16)\n\t"
|
||||
"lfd f10, 72(r16)\n\t"
|
||||
"lfd f11, 80(r16)\n\t"
|
||||
"lfd f12, 88(r16)\n\t"
|
||||
"lfd f13, 96(r16)\n\t"
|
||||
|
||||
"lwz r6, 16(r17)\n\t" /* load int registers from (r17) */
|
||||
"lwz r7, 20(r17)\n\t"
|
||||
"lwz r8, 24(r17)\n\t"
|
||||
"lwz r9, 28(r17)\n\t"
|
||||
"lwz r10, 32(r17)\n\t"
|
||||
"lwz r5, 8(r17)\n\t"
|
||||
"lwz r4, 4(r17)\n\t"
|
||||
"lwz r3, 0(r17)\n\t"
|
||||
|
||||
"mtctr r15\n\t" /* call the function stored in r15 */
|
||||
"bctrl \n\t"
|
||||
"mr r1,r29\n\t" /* restore stack and return pointer */
|
||||
"lwz r0,8(r1)\n\t"
|
||||
"mtlr r0\n\t"
|
||||
"stw r3,0(r17)\n\t" /* store function's output */
|
||||
"stw r4,4(r17)\n\t"
|
||||
"stfd f1,0(r16)\n\t"
|
||||
|
||||
:: [bufsize] "r" (bufsize), [buf] "r" (buf), [registers] "r" (registers->registers),
|
||||
[fp_registers] "r" (registers->fp_registers), [fptr] "r" (_f_ptr)
|
||||
: "r5","r6","r17","r16","r29","r13","r14");
|
||||
|
||||
|
||||
void *data = registers->registers;
|
||||
if (return_type <= ECL_FFI_UNSIGNED_LONG) {
|
||||
fficall->output.i = *((unsigned long *)data);
|
||||
} else if (return_type == ECL_FFI_POINTER_VOID) {
|
||||
fficall->output.pv = *((void **)data);
|
||||
} else if (return_type == ECL_FFI_CSTRING) {
|
||||
fficall->output.pc = *((char *)data);
|
||||
} else if (return_type == ECL_FFI_OBJECT) {
|
||||
fficall->output.o = *((cl_object *)data);
|
||||
} else if (return_type == ECL_FFI_FLOAT) {
|
||||
fficall->output.f = registers->fp_registers[0];
|
||||
} else if (return_type == ECL_FFI_DOUBLE) {
|
||||
fficall->output.d = registers->fp_registers[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
ecl_dynamic_callback_make(cl_object data, enum ecl_ffi_calling_convention cc_type)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
|
@ -1,342 +0,0 @@
|
|||
/* -*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*- */
|
||||
/* vim: set filetype=c tabstop=8 shiftwidth=4 expandtab: */
|
||||
|
||||
/*
|
||||
ffi_x86.c -- Nonportable component of the FFI
|
||||
*/
|
||||
/*
|
||||
Copyright (c) 2005, Juan Jose Garcia Ripoll.
|
||||
|
||||
ECL is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
See file '../Copyright' for full details.
|
||||
*/
|
||||
|
||||
#include <ecl/ecl.h>
|
||||
#include <string.h>
|
||||
#include <ecl/internal.h>
|
||||
|
||||
#if !defined(HAVE_LIBFFI)
|
||||
|
||||
struct ecl_fficall_reg *
|
||||
ecl_fficall_prepare_extra(struct ecl_fficall_reg *registers)
|
||||
{
|
||||
/* No need to prepare registers */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ecl_fficall_push_arg(union ecl_ffi_values *data, enum ecl_ffi_tag type)
|
||||
{
|
||||
int i;
|
||||
switch (type) {
|
||||
case ECL_FFI_CHAR: i = data->c; goto INT_ECL;
|
||||
case ECL_FFI_UNSIGNED_CHAR: i = data->uc; goto INT_ECL;
|
||||
case ECL_FFI_BYTE: i = data->b; goto INT_ECL;
|
||||
case ECL_FFI_UNSIGNED_BYTE: i = data->ub; goto INT_ECL;
|
||||
case ECL_FFI_SHORT: i = data->s; goto INT_ECL;
|
||||
case ECL_FFI_UNSIGNED_SHORT: i = data->us; goto INT_ECL;
|
||||
#ifdef ecl_uint8_t
|
||||
case ECL_FFI_INT8_T: i = data->i8; goto INT_ECL;
|
||||
case ECL_FFI_UINT8_T: i = data->u8; goto INT_ECL;
|
||||
#endif
|
||||
#ifdef ecl_uint16_t
|
||||
case ECL_FFI_INT16_T: i = data->i16; goto INT_ECL;
|
||||
case ECL_FFI_UINT16_T: i = data->u16; goto INT_ECL;
|
||||
#endif
|
||||
case ECL_FFI_INT:
|
||||
case ECL_FFI_LONG:
|
||||
case ECL_FFI_UNSIGNED_INT:
|
||||
case ECL_FFI_UNSIGNED_LONG:
|
||||
#ifdef ecl_uint32_t
|
||||
case ECL_FFI_INT32_T:
|
||||
case ECL_FFI_UINT32_T:
|
||||
#endif
|
||||
case ECL_FFI_POINTER_VOID:
|
||||
case ECL_FFI_CSTRING:
|
||||
case ECL_FFI_OBJECT:
|
||||
i = data->i;
|
||||
INT_ECL:
|
||||
ecl_fficall_align(sizeof(int));
|
||||
ecl_fficall_push_int(i);
|
||||
break;
|
||||
case ECL_FFI_DOUBLE:
|
||||
ecl_fficall_align(sizeof(int));
|
||||
ecl_fficall_push_bytes(&data->d, sizeof(double));
|
||||
break;
|
||||
case ECL_FFI_FLOAT:
|
||||
ecl_fficall_align(sizeof(int));
|
||||
ecl_fficall_push_bytes(&data->f, sizeof(float));
|
||||
break;
|
||||
#ifdef ecl_uint64_t
|
||||
case ECL_FFI_UINT64_T:
|
||||
case ECL_FFI_INT64_T:
|
||||
ecl_fficall_align(sizeof(ecl_uint64_t));
|
||||
ecl_fficall_push_bytes(&data->ull, sizeof(ecl_uint64_t));
|
||||
break;
|
||||
#endif
|
||||
#ifdef ecl_long_long_t
|
||||
case ECL_FFI_UNSIGNED_LONG_LONG:
|
||||
case ECL_FFI_LONG_LONG:
|
||||
ecl_fficall_align(sizeof(unsigned long));
|
||||
ecl_fficall_push_bytes(&data->ull, sizeof(unsigned long long));
|
||||
break;
|
||||
#endif
|
||||
case ECL_FFI_VOID:
|
||||
FEerror("VOID is not a valid argument type for a C function", 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ecl_fficall_execute(void *f_ptr, struct ecl_fficall *fficall, enum ecl_ffi_tag return_type)
|
||||
{
|
||||
int bufsize = fficall->buffer_size;
|
||||
char* buf = fficall->buffer;
|
||||
char* stack_p;
|
||||
#ifdef _MSC_VER
|
||||
__asm
|
||||
{
|
||||
mov stack_p,esp
|
||||
sub esp,bufsize
|
||||
mov esi,buf
|
||||
mov edi,esp
|
||||
mov ecx,bufsize
|
||||
rep movsb
|
||||
}
|
||||
#else
|
||||
asm volatile (
|
||||
"movl %%esp, %0\n\t"
|
||||
"subl %1, %%esp\n\t"
|
||||
"movl %2, %%esi\n\t"
|
||||
"movl %%esp, %%edi\n\t"
|
||||
"rep\n\t"
|
||||
"movsb\n\t"
|
||||
: "=a" (stack_p) : "c" (bufsize), "d" (buf) : "%edi", "%esi");
|
||||
#endif
|
||||
if (return_type <= ECL_FFI_UNSIGNED_LONG) {
|
||||
fficall->output.i = ((int (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_POINTER_VOID) {
|
||||
fficall->output.pv = ((void * (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_CSTRING) {
|
||||
fficall->output.pc = ((char * (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_OBJECT) {
|
||||
fficall->output.o = ((cl_object (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_FLOAT) {
|
||||
fficall->output.f = ((float (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_DOUBLE) {
|
||||
fficall->output.d = ((double (*)())f_ptr)();
|
||||
}
|
||||
#ifdef ecl_uint8_t
|
||||
else if (return_type == ECL_FFI_INT8_T) {
|
||||
fficall->output.i8 = ((ecl_int8_t (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_UINT16_T) {
|
||||
fficall->output.u8 = ((ecl_uint8_t (*)())f_ptr)();
|
||||
}
|
||||
#endif
|
||||
#ifdef ecl_uint16_t
|
||||
else if (return_type == ECL_FFI_INT16_T) {
|
||||
fficall->output.i16 = ((ecl_int16_t (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_UINT16_T) {
|
||||
fficall->output.u16 = ((ecl_uint16_t (*)())f_ptr)();
|
||||
}
|
||||
#endif
|
||||
#ifdef ecl_uint32_t
|
||||
else if (return_type == ECL_FFI_INT32_T) {
|
||||
fficall->output.i32 = ((ecl_int32_t (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_UINT32_T) {
|
||||
fficall->output.u32 = ((ecl_uint32_t (*)())f_ptr)();
|
||||
}
|
||||
#endif
|
||||
#ifdef ecl_uint64_t
|
||||
else if (return_type == ECL_FFI_INT64_T) {
|
||||
fficall->output.i64 = ((ecl_int64_t (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_UINT32_T) {
|
||||
fficall->output.u64 = ((ecl_uint64_t (*)())f_ptr)();
|
||||
}
|
||||
#endif
|
||||
#ifdef ecl_long_long_t
|
||||
else if (return_type == ECL_FFI_LONG_LONG) {
|
||||
fficall->output.ll = ((ecl_long_long_t (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_UNSIGNED_LONG_LONG) {
|
||||
fficall->output.ull = ((ecl_ulong_long_t (*)())f_ptr)();
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
((void (*)())f_ptr)();
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
__asm mov esp,stack_p
|
||||
#else
|
||||
asm volatile ("mov %0,%%esp" :: "a" (stack_p));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ecl_dynamic_callback_execute(cl_object cbk_info, char *arg_buffer)
|
||||
{
|
||||
cl_object fun, rtype, argtypes;
|
||||
cl_object result;
|
||||
cl_index i, size;
|
||||
union ecl_ffi_values output;
|
||||
enum ecl_ffi_tag tag;
|
||||
cl_env_ptr env = ecl_process_env();
|
||||
|
||||
ECL_BUILD_STACK_FRAME(env, frame, aux);
|
||||
|
||||
fun = CAR(cbk_info);
|
||||
rtype = CADR(cbk_info);
|
||||
argtypes = CADDR(cbk_info);
|
||||
|
||||
arg_buffer += 4; /* Skip return address */
|
||||
for (i=0; !ecl_endp(argtypes); argtypes = CDR(argtypes), i++) {
|
||||
tag = ecl_foreign_type_code(CAR(argtypes));
|
||||
size = ecl_fixnum(si_size_of_foreign_elt_type(CAR(argtypes)));
|
||||
result = ecl_foreign_data_ref_elt(arg_buffer, tag);
|
||||
ecl_stack_frame_push(frame,result);
|
||||
{
|
||||
int mask = 3;
|
||||
int sp = (size + mask) & ~mask;
|
||||
arg_buffer += (sp);
|
||||
}
|
||||
}
|
||||
|
||||
result = ecl_apply_from_stack_frame(frame, fun);
|
||||
ecl_stack_frame_close(frame);
|
||||
|
||||
tag = ecl_foreign_type_code(rtype);
|
||||
memset(&output, 0, sizeof(output));
|
||||
ecl_foreign_data_set_elt(&output, tag, result);
|
||||
|
||||
switch (tag) {
|
||||
case ECL_FFI_CHAR: i = output.c; goto INT_ECL;
|
||||
case ECL_FFI_UNSIGNED_CHAR: i = output.uc; goto INT_ECL;
|
||||
case ECL_FFI_BYTE: i = output.b; goto INT_ECL;
|
||||
case ECL_FFI_UNSIGNED_BYTE: i = output.ub; goto INT_ECL;
|
||||
#ifdef ecl_uint8_t
|
||||
case ECL_FFI_INT8_T: i = output.i8; goto INT_ECL;
|
||||
case ECL_FFI_UINT8_T: i = output.u8; goto INT_ECL;
|
||||
#endif
|
||||
#ifdef ecl_uint16_t
|
||||
case ECL_FFI_INT16_T:
|
||||
#endif
|
||||
case ECL_FFI_SHORT: i = output.s; goto INT_ECL;
|
||||
#ifdef ecl_uint16_t
|
||||
case ECL_FFI_UINT16_T:
|
||||
#endif
|
||||
case ECL_FFI_UNSIGNED_SHORT: i = output.us; goto INT_ECL;
|
||||
case ECL_FFI_POINTER_VOID:
|
||||
case ECL_FFI_OBJECT:
|
||||
case ECL_FFI_CSTRING:
|
||||
case ECL_FFI_INT:
|
||||
case ECL_FFI_UNSIGNED_INT:
|
||||
#ifdef ecl_uint32_t
|
||||
case ECL_FFI_INT32_T:
|
||||
case ECL_FFI_UINT32_T:
|
||||
#endif
|
||||
case ECL_FFI_LONG:
|
||||
case ECL_FFI_UNSIGNED_LONG:
|
||||
i = output.i;
|
||||
INT_ECL:
|
||||
#ifdef _MSC_VER
|
||||
__asm mov eax,i
|
||||
#else
|
||||
{
|
||||
register int eax asm("eax");
|
||||
eax = i;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
#if defined(ecl_long_long_t) || defined(ecl_uint64_t)
|
||||
# ifdef ecl_long_long_t
|
||||
case ECL_FFI_LONG_LONG:
|
||||
case ECL_FFI_UNSIGNED_LONG_LONG:
|
||||
# endif
|
||||
# ifdef ecl_uint64_t
|
||||
case ECL_FFI_INT64_T:
|
||||
case ECL_FFI_UINT64_T:
|
||||
# endif
|
||||
# ifdef _MSC_VER
|
||||
__asm mov eax,output.l2[0]
|
||||
__asm mov edx,output.l2[1]
|
||||
# else
|
||||
{
|
||||
register int eax asm("eax");
|
||||
register int edx asm("edx");
|
||||
eax = output.l2[0];
|
||||
edx = output.l2[1];
|
||||
}
|
||||
# endif
|
||||
return;
|
||||
#endif /* ecl_long_long_t */
|
||||
case ECL_FFI_DOUBLE: {
|
||||
#ifdef _MSC_VER
|
||||
__asm fld output.d
|
||||
#else
|
||||
{
|
||||
asm("fldl (%0)" :: "a" (&output.d));
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
case ECL_FFI_FLOAT: {
|
||||
#ifdef _MSC_VER
|
||||
__asm fld output.f
|
||||
#else
|
||||
{
|
||||
asm("flds (%0)" :: "a" (&output.f));
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
case ECL_FFI_VOID:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
ecl_dynamic_callback_make(cl_object data, enum ecl_ffi_calling_convention cc_type)
|
||||
{
|
||||
/*
|
||||
* push %esp 54
|
||||
* pushl <data> 68 <addr32>
|
||||
* call ecl_dynamic_callback_call E8 <disp32>
|
||||
* [ Here we could use also lea 4(%esp), %esp, but %ecx seems to be free ]
|
||||
* pop %ecx 59
|
||||
* pop %ecx 59
|
||||
* ret c3
|
||||
* nop 90
|
||||
* nop 90
|
||||
*/
|
||||
char *buf = (char*)ecl_alloc_atomic_align(sizeof(char)*16, 4);
|
||||
*(char*) (buf+0) = 0x54;
|
||||
*(char*) (buf+1) = 0x68;
|
||||
*(long*) (buf+2) = (long)data;
|
||||
*(unsigned char*) (buf+6) = 0xE8;
|
||||
*(long*) (buf+7) = (long)ecl_dynamic_callback_execute - (long)(buf+11);
|
||||
*(char*) (buf+11) = 0x59;
|
||||
*(char*) (buf+12) = 0x59;
|
||||
if (cc_type == ECL_FFI_CC_CDECL) {
|
||||
*(unsigned char*) (buf+13) = 0xc3;
|
||||
*(unsigned short*)(buf+14) = 0x9090;
|
||||
} else {
|
||||
cl_object arg_types = CADDR(data);
|
||||
int byte_size = 0;
|
||||
int mask = 3;
|
||||
|
||||
while (CONSP(arg_types)) {
|
||||
int sz = ecl_fixnum(si_size_of_foreign_elt_type(CAR(arg_types)));
|
||||
byte_size += ((sz+mask)&(~mask));
|
||||
arg_types = CDR(arg_types);
|
||||
}
|
||||
|
||||
*(unsigned char*) (buf+13) = 0xc2;
|
||||
*(unsigned short*)(buf+14) = (unsigned short)byte_size;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,370 +0,0 @@
|
|||
/* -*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*- */
|
||||
/* vim: set filetype=c tabstop=8 shiftwidth=4 expandtab: */
|
||||
|
||||
/*
|
||||
ffi_x86.c -- Nonportable component of the FFI
|
||||
*/
|
||||
/*
|
||||
Copyright (c) 2005, Juan Jose Garcia Ripoll.
|
||||
|
||||
ECL is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
See file '../Copyright' for full details.
|
||||
*/
|
||||
|
||||
#include <ecl/ecl.h>
|
||||
#include <string.h>
|
||||
#include <ecl/internal.h>
|
||||
|
||||
#if !defined(HAVE_LIBFFI)
|
||||
|
||||
#define MAX_INT_REGISTERS 6
|
||||
#define MAX_FP_REGISTERS 8
|
||||
|
||||
struct ecl_fficall_reg {
|
||||
long int_registers[MAX_INT_REGISTERS];
|
||||
int int_registers_size;
|
||||
double fp_registers[MAX_FP_REGISTERS];
|
||||
int fp_registers_size;
|
||||
};
|
||||
|
||||
struct ecl_fficall_reg *
|
||||
ecl_fficall_prepare_extra(struct ecl_fficall_reg *registers)
|
||||
{
|
||||
if (registers == 0) {
|
||||
registers = ecl_alloc_atomic_align(sizeof(*registers), sizeof(long));
|
||||
}
|
||||
registers->int_registers_size = 0;
|
||||
registers->fp_registers_size = 0;
|
||||
return registers;
|
||||
}
|
||||
|
||||
void
|
||||
ecl_fficall_push_arg(union ecl_ffi_values *data, enum ecl_ffi_tag type)
|
||||
{
|
||||
long i;
|
||||
struct ecl_fficall *fficall = cl_env.fficall;
|
||||
struct ecl_fficall_reg *registers = fficall->registers;
|
||||
switch (type) {
|
||||
case ECL_FFI_CHAR: i = data->c; goto INT;
|
||||
case ECL_FFI_UNSIGNED_CHAR: i = data->uc; goto INT;
|
||||
#ifdef ecl_uint8_t
|
||||
case ECL_FFI_INT8_T: i = data->i8; goto INT;
|
||||
case ECL_FFI_UINT8_T: i = data->u8; goto INT;
|
||||
#endif
|
||||
case ECL_FFI_BYTE: i = data->b; goto INT;
|
||||
case ECL_FFI_UNSIGNED_BYTE: i = data->ub; goto INT;
|
||||
#ifdef ecl_uint16_t
|
||||
case ECL_FFI_INT16_T: i = data->i16; goto INT;
|
||||
case ECL_FFI_UINT16_T: i = data->u16; goto INT;
|
||||
#endif
|
||||
case ECL_FFI_SHORT: i = data->s; goto INT;
|
||||
case ECL_FFI_UNSIGNED_SHORT: i = data->us; goto INT;
|
||||
#ifdef ecl_uint32_t
|
||||
case ECL_FFI_INT32_T: i = data->i32; goto INT;
|
||||
case ECL_FFI_UINT32_T: i = data->u32; goto INT;
|
||||
#endif
|
||||
case ECL_FFI_INT: i = data->i; goto INT;
|
||||
case ECL_FFI_UNSIGNED_INT: i = data->ui; goto INT;
|
||||
case ECL_FFI_LONG:
|
||||
case ECL_FFI_UNSIGNED_LONG:
|
||||
#ifdef ecl_uint64_t
|
||||
case ECL_FFI_INT64_T:
|
||||
case ECL_FFI_UINT64_T:
|
||||
#endif
|
||||
case ECL_FFI_POINTER_VOID:
|
||||
case ECL_FFI_CSTRING:
|
||||
case ECL_FFI_OBJECT:
|
||||
i = data->l;
|
||||
INT:
|
||||
if (registers->int_registers_size < MAX_INT_REGISTERS) {
|
||||
registers->int_registers[registers->int_registers_size++] = i;
|
||||
} else {
|
||||
ecl_fficall_align(sizeof(long));
|
||||
ecl_fficall_push_bytes(&i, sizeof(long));
|
||||
}
|
||||
break;
|
||||
case ECL_FFI_DOUBLE:
|
||||
if (registers->fp_registers_size < MAX_FP_REGISTERS) {
|
||||
registers->fp_registers[registers->fp_registers_size++] = data->d;
|
||||
} else {
|
||||
ecl_fficall_align(sizeof(long));
|
||||
ecl_fficall_push_bytes(&data->d, sizeof(double));
|
||||
}
|
||||
break;
|
||||
case ECL_FFI_FLOAT:
|
||||
if (registers->fp_registers_size < MAX_FP_REGISTERS) {
|
||||
memset(®isters->fp_registers[registers->fp_registers_size], 0, sizeof(double));
|
||||
(*(float*)(®isters->fp_registers[registers->fp_registers_size++])) = (float)data->f;
|
||||
} else {
|
||||
i = 0;
|
||||
ecl_fficall_align(sizeof(long));
|
||||
ecl_fficall_push_bytes(&data->f, sizeof(float));
|
||||
ecl_fficall_push_bytes(&i, sizeof(float));
|
||||
}
|
||||
break;
|
||||
case ECL_FFI_VOID:
|
||||
FEerror("VOID is not a valid argument type for a C function", 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ecl_fficall_execute(void *_f_ptr, struct ecl_fficall *fficall, enum ecl_ffi_tag return_type)
|
||||
{
|
||||
struct ecl_fficall_reg *registers = fficall->registers;
|
||||
long bufsize = fficall->buffer_size;
|
||||
char* buf = fficall->buffer;
|
||||
char* stack_p;
|
||||
register void* f_ptr asm("r10");
|
||||
|
||||
ecl_fficall_align(16);
|
||||
bufsize = fficall->buffer_size;
|
||||
f_ptr = _f_ptr;
|
||||
|
||||
asm volatile (
|
||||
"mov %%rsp, %0\n\t"
|
||||
"sub %1, %%rsp\n\t"
|
||||
"mov %2, %%rsi\n\t"
|
||||
"mov %%rsp, %%rdi\n\t"
|
||||
"rep\n\t"
|
||||
"movsb\n\t"
|
||||
: "=a" (stack_p) : "c" (bufsize), "d" (buf) : "%rdi", "%rsi");
|
||||
|
||||
asm volatile (
|
||||
"mov (%%rax), %%rdi\n\t"
|
||||
"mov 0x08(%%rax), %%rsi\n\t"
|
||||
"mov 0x10(%%rax), %%rdx\n\t"
|
||||
"mov 0x18(%%rax), %%rcx\n\t"
|
||||
"mov 0x20(%%rax), %%r8\n\t"
|
||||
"mov 0x28(%%rax), %%r9\n\t"
|
||||
:: "a" (registers->int_registers));
|
||||
|
||||
asm volatile (
|
||||
"movsd (%%rax), %%xmm0\n\t"
|
||||
"movsd 0x08(%%rax), %%xmm1\n\t"
|
||||
"movsd 0x10(%%rax), %%xmm2\n\t"
|
||||
"movsd 0x18(%%rax), %%xmm3\n\t"
|
||||
"movsd 0x20(%%rax), %%xmm4\n\t"
|
||||
"movsd 0x28(%%rax), %%xmm5\n\t"
|
||||
"movsd 0x30(%%rax), %%xmm6\n\t"
|
||||
"movsd 0x38(%%rax), %%xmm7\n\t"
|
||||
:: "a" (registers->fp_registers));
|
||||
|
||||
if (return_type <= ECL_FFI_UNSIGNED_LONG) {
|
||||
fficall->output.ul = ((unsigned long (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_POINTER_VOID) {
|
||||
fficall->output.pv = ((void * (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_CSTRING) {
|
||||
fficall->output.pc = ((char * (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_OBJECT) {
|
||||
fficall->output.o = ((cl_object (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_FLOAT) {
|
||||
fficall->output.f = ((float (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_DOUBLE) {
|
||||
fficall->output.d = ((double (*)())f_ptr)();
|
||||
}
|
||||
#ifdef ecl_uint8_t
|
||||
else if (return_type == ECL_FFI_INT8_T) {
|
||||
fficall->output.i8 = ((ecl_int8_t (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_UINT16_T) {
|
||||
fficall->output.u8 = ((ecl_uint8_t (*)())f_ptr)();
|
||||
}
|
||||
#endif
|
||||
#ifdef ecl_uint16_t
|
||||
else if (return_type == ECL_FFI_INT16_T) {
|
||||
fficall->output.i16 = ((ecl_int16_t (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_UINT16_T) {
|
||||
fficall->output.u16 = ((ecl_uint16_t (*)())f_ptr)();
|
||||
}
|
||||
#endif
|
||||
#ifdef ecl_uint32_t
|
||||
else if (return_type == ECL_FFI_INT32_T) {
|
||||
fficall->output.i32 = ((ecl_int32_t (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_UINT32_T) {
|
||||
fficall->output.u32 = ((ecl_uint32_t (*)())f_ptr)();
|
||||
}
|
||||
#endif
|
||||
#ifdef ecl_uint64_t
|
||||
else if (return_type == ECL_FFI_INT64_T) {
|
||||
fficall->output.i64 = ((ecl_int64_t (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_UINT32_T) {
|
||||
fficall->output.u64 = ((ecl_uint64_t (*)())f_ptr)();
|
||||
}
|
||||
#endif
|
||||
#ifdef ecl_long_long_t
|
||||
else if (return_type == ECL_FFI_LONG_LONG) {
|
||||
fficall->output.ll = ((ecl_long_long_t (*)())f_ptr)();
|
||||
} else if (return_type == ECL_FFI_UNSIGNED_LONG_LONG) {
|
||||
fficall->output.ull = ((ecl_ulong_long_t (*)())f_ptr)();
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
((void (*)())f_ptr)();
|
||||
}
|
||||
|
||||
asm volatile ("mov %0,%%rsp" :: "a" (stack_p));
|
||||
}
|
||||
|
||||
static void
|
||||
ecl_dynamic_callback_execute(long i1, long i2, long i3, long i4, long i5, long i6,
|
||||
double f1, double f2, double f3, double f4,
|
||||
double f5, double f6, double f7, double f8,
|
||||
cl_object cbk_info, char *arg_buffer)
|
||||
{
|
||||
cl_object fun, rtype, argtypes;
|
||||
cl_object result;
|
||||
cl_index i, size, i_reg_index, f_reg_index;
|
||||
union ecl_ffi_values output;
|
||||
enum ecl_ffi_tag tag;
|
||||
long i_reg[MAX_INT_REGISTERS];
|
||||
double f_reg[MAX_FP_REGISTERS];
|
||||
cl_env_ptr env = ecl_process_env();
|
||||
|
||||
ECL_BUILD_STACK_FRAME(env, frame, aux);
|
||||
|
||||
fun = CAR(cbk_info);
|
||||
rtype = CADR(cbk_info);
|
||||
argtypes = CADDR(cbk_info);
|
||||
|
||||
i_reg_index = f_reg_index = 0;
|
||||
i_reg[0] = i1;
|
||||
i_reg[1] = i2;
|
||||
i_reg[2] = i3;
|
||||
i_reg[3] = i4;
|
||||
i_reg[4] = i5;
|
||||
i_reg[5] = i6;
|
||||
f_reg[0] = f1;
|
||||
f_reg[1] = f2;
|
||||
f_reg[2] = f3;
|
||||
f_reg[3] = f4;
|
||||
f_reg[4] = f5;
|
||||
f_reg[5] = f6;
|
||||
f_reg[6] = f7;
|
||||
f_reg[7] = f8;
|
||||
|
||||
arg_buffer += 2*sizeof(void*); /* Skip return address and base pointer */
|
||||
for (i=0; !ecl_endp(argtypes); argtypes = CDR(argtypes), i++) {
|
||||
tag = ecl_foreign_type_code(CAR(argtypes));
|
||||
size = ecl_fixnum(si_size_of_foreign_elt_type(CAR(argtypes)));
|
||||
if (tag <= ECL_FFI_OBJECT) {
|
||||
if (i_reg_index < MAX_INT_REGISTERS)
|
||||
result = ecl_foreign_data_ref_elt(&i_reg[i_reg_index++], tag);
|
||||
else
|
||||
goto ARG_FROM_STACK;
|
||||
} else if (tag <= ECL_FFI_DOUBLE) {
|
||||
if (f_reg_index < MAX_FP_REGISTERS)
|
||||
result = ecl_foreign_data_ref_elt(&f_reg[f_reg_index++], tag);
|
||||
else
|
||||
goto ARG_FROM_STACK;
|
||||
} else {
|
||||
ARG_FROM_STACK:
|
||||
result = ecl_foreign_data_ref_elt(arg_buffer, tag);
|
||||
{
|
||||
int mask = 7;
|
||||
int sp = (size + mask) & ~mask;
|
||||
arg_buffer += (sp);
|
||||
}
|
||||
}
|
||||
ecl_stack_frame_push(frame, result);
|
||||
}
|
||||
|
||||
result = ecl_apply_from_stack_frame(frame, fun);
|
||||
ecl_stack_frame_close(frame);
|
||||
|
||||
tag = ecl_foreign_type_code(rtype);
|
||||
memset(&output, 0, sizeof(output));
|
||||
ecl_foreign_data_set_elt(&output, tag, result);
|
||||
|
||||
switch (tag) {
|
||||
case ECL_FFI_CHAR: i = output.c; goto INT;
|
||||
case ECL_FFI_UNSIGNED_CHAR: i = output.uc; goto INT;
|
||||
case ECL_FFI_BYTE: i = output.b; goto INT;
|
||||
case ECL_FFI_UNSIGNED_BYTE: i = output.ub; goto INT;
|
||||
#ifdef ecl_uint8_t
|
||||
case ECL_FFI_INT8_T: i = output.i8; goto INT;
|
||||
case ECL_FFI_UINT8_T: i = output.u8; goto INT;
|
||||
#endif
|
||||
#ifdef ecl_uint16_t
|
||||
case ECL_FFI_INT16_T: i = output.i16; goto INT;
|
||||
case ECL_FFI_UINT16_T: i = output.u16; goto INT;
|
||||
#endif
|
||||
case ECL_FFI_SHORT: i = output.s; goto INT;
|
||||
case ECL_FFI_UNSIGNED_SHORT: i = output.us; goto INT;
|
||||
#ifdef ecl_uint32_t
|
||||
case ECL_FFI_INT32_T: i = output.i32; goto INT;
|
||||
case ECL_FFI_UINT32_T: i = output.u32; goto INT;
|
||||
#endif
|
||||
case ECL_FFI_POINTER_VOID:
|
||||
case ECL_FFI_OBJECT:
|
||||
case ECL_FFI_CSTRING:
|
||||
case ECL_FFI_INT:
|
||||
case ECL_FFI_UNSIGNED_INT:
|
||||
case ECL_FFI_LONG:
|
||||
case ECL_FFI_UNSIGNED_LONG:
|
||||
#ifdef ecl_uint64_t
|
||||
case ECL_FFI_INT64_T:
|
||||
case ECL_FFI_UINT64_T:
|
||||
#endif
|
||||
i = output.i;
|
||||
INT:
|
||||
{
|
||||
register long eax asm("rax");
|
||||
eax = i;
|
||||
}
|
||||
return;
|
||||
case ECL_FFI_DOUBLE: {
|
||||
{
|
||||
asm("movsd (%0),%%xmm0" :: "a" (&output.d));
|
||||
}
|
||||
return;
|
||||
}
|
||||
case ECL_FFI_FLOAT: {
|
||||
{
|
||||
asm("movss (%0),%%xmm0" :: "a" (&output.f));
|
||||
}
|
||||
return;
|
||||
}
|
||||
case ECL_FFI_VOID:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
ecl_dynamic_callback_make(cl_object data, enum ecl_ffi_calling_convention cc_type)
|
||||
{
|
||||
/*
|
||||
* push %rbp 55
|
||||
* push %rsp 54
|
||||
* mov <addr64>,%rax 48 b8 <addr64>
|
||||
* push %rax 50
|
||||
* mov <addr64>,%rax 48 b8 <addr64>
|
||||
* callq *%rax 48 ff d0
|
||||
* pop %rcx 59
|
||||
* pop %rcx 59
|
||||
* pop %rbp 5d
|
||||
* ret c3
|
||||
* nop 90
|
||||
* nop 90
|
||||
*/
|
||||
char *buf = (char*)ecl_alloc_atomic_align(sizeof(char)*32, 8);
|
||||
*(char*) (buf+0) = 0x55;
|
||||
*(char*) (buf+1) = 0x54;
|
||||
*(short*)(buf+2) = 0xb848;
|
||||
*(long*) (buf+4) = (long)data;
|
||||
*(char*) (buf+12) = 0x50;
|
||||
*(short*)(buf+13) = 0xb848;
|
||||
*(long*) (buf+15) = (long)ecl_dynamic_callback_execute;
|
||||
*(int*) (buf+23) = (int)0x00d0ff48; /* leading null byte is overwritten */
|
||||
*(char*) (buf+26) = 0x59;
|
||||
*(char*) (buf+27) = 0x59;
|
||||
*(char*) (buf+28) = 0x5d;
|
||||
*(char*) (buf+29) = 0xc3;
|
||||
*(short*)(buf+30) = 0x9090;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -74,7 +74,7 @@ ecl_def_string_array(feature_names,static,const) = {
|
|||
#ifdef ECL_CLOS_STREAMS
|
||||
ecl_def_string_array_elt("CLOS-STREAMS"),
|
||||
#endif
|
||||
#if defined(ECL_DYNAMIC_FFI) || defined(HAVE_LIBFFI)
|
||||
#if defined(HAVE_LIBFFI)
|
||||
ecl_def_string_array_elt("DFFI"),
|
||||
#endif
|
||||
#ifdef ECL_UNICODE
|
||||
|
|
|
|||
123
src/c/ffi.d
123
src/c/ffi.d
|
|
@ -125,13 +125,6 @@ ecl_foreign_type_table[] = {
|
|||
{@':void', 0, 0}
|
||||
};
|
||||
|
||||
#ifdef ECL_DYNAMIC_FFI
|
||||
static const cl_object ecl_foreign_cc_table[] = {
|
||||
@':cdecl',
|
||||
@':stdcall'
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBFFI
|
||||
static struct {
|
||||
const cl_object symbol;
|
||||
|
|
@ -433,20 +426,6 @@ ecl_foreign_cc_code(cl_object cc)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef ECL_DYNAMIC_FFI
|
||||
enum ecl_ffi_calling_convention
|
||||
ecl_foreign_cc_code(cl_object cc)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= ECL_FFI_CC_STDCALL; i++) {
|
||||
if (cc == ecl_foreign_cc_table[i])
|
||||
return (enum ecl_ffi_calling_convention)i;
|
||||
}
|
||||
FEerror("~A does no denote a valid calling convention.", 1, cc);
|
||||
return ECL_FFI_CC_CDECL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void wrong_ffi_tag(enum ecl_ffi_tag tag) ecl_attr_noreturn;
|
||||
|
||||
static void
|
||||
|
|
@ -784,108 +763,6 @@ OUTPUT:
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef ECL_DYNAMIC_FFI
|
||||
static void
|
||||
ecl_fficall_overflow()
|
||||
{
|
||||
FEerror("Stack overflow on SI:CALL-CFUN", 0);
|
||||
}
|
||||
|
||||
void
|
||||
ecl_fficall_prepare(cl_object return_type, cl_object arg_type, cl_object cc_type)
|
||||
{
|
||||
struct ecl_fficall *fficall = cl_env.fficall;
|
||||
fficall->buffer_sp = fficall->buffer;
|
||||
fficall->buffer_size = 0;
|
||||
fficall->cstring = ECL_NIL;
|
||||
fficall->cc = ecl_foreign_cc_code(cc_type);
|
||||
fficall->registers = ecl_fficall_prepare_extra(fficall->registers);
|
||||
}
|
||||
|
||||
void
|
||||
ecl_fficall_push_bytes(void *data, size_t bytes)
|
||||
{
|
||||
struct ecl_fficall *fficall = cl_env.fficall;
|
||||
fficall->buffer_size += bytes;
|
||||
if (fficall->buffer_size >= ECL_FFICALL_LIMIT)
|
||||
ecl_fficall_overflow();
|
||||
memcpy(fficall->buffer_sp, (char*)data, bytes);
|
||||
fficall->buffer_sp += bytes;
|
||||
}
|
||||
|
||||
void
|
||||
ecl_fficall_push_int(int data)
|
||||
{
|
||||
ecl_fficall_push_bytes(&data, sizeof(int));
|
||||
}
|
||||
|
||||
void
|
||||
ecl_fficall_align(int data)
|
||||
{
|
||||
struct ecl_fficall *fficall = cl_env.fficall;
|
||||
if (data == 1)
|
||||
return;
|
||||
else {
|
||||
size_t sp = fficall->buffer_sp - fficall->buffer;
|
||||
size_t mask = data - 1;
|
||||
size_t new_sp = (sp + mask) & ~mask;
|
||||
if (new_sp >= ECL_FFICALL_LIMIT)
|
||||
ecl_fficall_overflow();
|
||||
fficall->buffer_sp = fficall->buffer + new_sp;
|
||||
fficall->buffer_size = new_sp;
|
||||
}
|
||||
}
|
||||
|
||||
@(defun si::call-cfun (fun return_type arg_types args &optional (cc_type @':cdecl'))
|
||||
struct ecl_fficall *fficall = cl_env.fficall;
|
||||
void *cfun = ecl_foreign_data_pointer_safe(fun);
|
||||
cl_object object;
|
||||
enum ecl_ffi_tag return_type_tag = ecl_foreign_type_code(return_type);
|
||||
@
|
||||
|
||||
ecl_fficall_prepare(return_type, arg_types, cc_type);
|
||||
while (CONSP(arg_types)) {
|
||||
enum ecl_ffi_tag type;
|
||||
if (!CONSP(args)) {
|
||||
FEerror("In SI:CALL-CFUN, mismatch between argument types and argument list: ~A vs ~A", 0);
|
||||
}
|
||||
type = ecl_foreign_type_code(CAR(arg_types));
|
||||
if (type == ECL_FFI_CSTRING) {
|
||||
object = ecl_null_terminated_base_string(CAR(args));
|
||||
if (CAR(args) != object)
|
||||
fficall->cstring =
|
||||
CONS(object, fficall->cstring);
|
||||
} else {
|
||||
object = CAR(args);
|
||||
}
|
||||
ecl_foreign_data_set_elt(&fficall->output, type, object);
|
||||
ecl_fficall_push_arg(&fficall->output, type);
|
||||
arg_types = CDR(arg_types);
|
||||
args = CDR(args);
|
||||
}
|
||||
ecl_fficall_execute(cfun, fficall, return_type_tag);
|
||||
object = ecl_foreign_data_ref_elt(&fficall->output, return_type_tag);
|
||||
|
||||
fficall->buffer_size = 0;
|
||||
fficall->buffer_sp = fficall->buffer;
|
||||
fficall->cstring = ECL_NIL;
|
||||
|
||||
@(return object)
|
||||
@)
|
||||
|
||||
@(defun si::make-dynamic-callback (fun sym rtype argtypes &optional (cctype @':cdecl'))
|
||||
cl_object data;
|
||||
cl_object cbk;
|
||||
@
|
||||
data = cl_list(3, fun, rtype, argtypes);
|
||||
cbk = ecl_make_foreign_data(@':pointer-void', 0, ecl_dynamic_callback_make(data, ecl_foreign_cc_code(cctype)));
|
||||
|
||||
si_put_sysprop(sym, @':callback', CONS(cbk, data));
|
||||
@(return cbk)
|
||||
@)
|
||||
#endif /* ECL_DYNAMIC_FFI */
|
||||
|
||||
|
||||
#ifdef HAVE_LIBFFI
|
||||
static void
|
||||
resize_call_stack(cl_env_ptr env, cl_index new_size)
|
||||
|
|
|
|||
|
|
@ -164,10 +164,6 @@ ecl_init_env(cl_env_ptr env)
|
|||
env->ffi_values = 0;
|
||||
env->ffi_values_ptrs = 0;
|
||||
#endif
|
||||
#ifdef ECL_DYNAMIC_FFI
|
||||
env->fficall = ecl_alloc(sizeof(struct ecl_fficall));
|
||||
((struct ecl_fficall*)env->fficall)->registers = 0;
|
||||
#endif
|
||||
|
||||
env->method_cache = ecl_make_cache(64, 4096);
|
||||
env->slot_cache = ecl_make_cache(3, 4096);
|
||||
|
|
|
|||
|
|
@ -71,16 +71,11 @@ typedef struct {
|
|||
#else
|
||||
# define IF_SSE2(x) NULL
|
||||
#endif
|
||||
#if defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI)
|
||||
#if defined(HAVE_LIBFFI)
|
||||
# define IF_DFFI(x) x
|
||||
#else
|
||||
# define IF_DFFI(x) NULL
|
||||
#endif
|
||||
#if defined(HAVE_LIBFFI)
|
||||
# define IF_LIBFFI(x) x
|
||||
#else
|
||||
# define IF_LIBFFI(x) NULL
|
||||
#endif
|
||||
|
||||
cl_symbol_initializer
|
||||
cl_symbols[] = {
|
||||
|
|
@ -1749,12 +1744,12 @@ cl_symbols[] = {
|
|||
|
||||
{SYS_ "*CODE-WALKER*", SI_SPECIAL, NULL, -1, OBJNULL},
|
||||
|
||||
/* #if defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI) */
|
||||
/* #if defined(HAVE_LIBFFI) */
|
||||
{SYS_ "CALL-CFUN", SI_ORDINARY, IF_DFFI(si_call_cfun), -1, OBJNULL},
|
||||
{KEY_ "CALLBACK", KEYWORD, NULL, -1, OBJNULL},
|
||||
{SYS_ "MAKE-DYNAMIC-CALLBACK", SI_ORDINARY, IF_DFFI(si_make_dynamic_callback), -1, OBJNULL},
|
||||
{SYS_ "FREE-FFI-CLOSURE", SI_ORDINARY, IF_LIBFFI(si_free_ffi_closure), 1, OBJNULL},
|
||||
/* #endif defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI) */
|
||||
{SYS_ "FREE-FFI-CLOSURE", SI_ORDINARY, IF_DFFI(si_free_ffi_closure), 1, OBJNULL},
|
||||
/* #endif defined(HAVE_LIBFFI) */
|
||||
{KEY_ "CDECL", KEYWORD, NULL, -1, OBJNULL},
|
||||
{KEY_ "STDCALL", KEYWORD, NULL, -1, OBJNULL},
|
||||
|
||||
|
|
|
|||
|
|
@ -71,16 +71,11 @@ typedef struct {
|
|||
#else
|
||||
# define IF_SSE2(x) NULL
|
||||
#endif
|
||||
#if defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI)
|
||||
#if defined(HAVE_LIBFFI)
|
||||
# define IF_DFFI(x) x
|
||||
#else
|
||||
# define IF_DFFI(x) NULL
|
||||
#endif
|
||||
#if defined(HAVE_LIBFFI)
|
||||
# define IF_LIBFFI(x) x
|
||||
#else
|
||||
# define IF_LIBFFI(x) NULL
|
||||
#endif
|
||||
|
||||
cl_symbol_initializer
|
||||
cl_symbols[] = {
|
||||
|
|
@ -1749,12 +1744,12 @@ cl_symbols[] = {
|
|||
|
||||
{SYS_ "*CODE-WALKER*",NULL},
|
||||
|
||||
/* #if defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI) */
|
||||
/* #if defined(HAVE_LIBFFI) */
|
||||
{SYS_ "CALL-CFUN",IF_DFFI("si_call_cfun")},
|
||||
{KEY_ "CALLBACK",NULL},
|
||||
{SYS_ "MAKE-DYNAMIC-CALLBACK",IF_DFFI("si_make_dynamic_callback")},
|
||||
{SYS_ "FREE-FFI-CLOSURE",IF_LIBFFI("si_free_ffi_closure")},
|
||||
/* #endif defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI) */
|
||||
{SYS_ "FREE-FFI-CLOSURE",IF_DFFI("si_free_ffi_closure")},
|
||||
/* #endif defined(HAVE_LIBFFI) */
|
||||
{KEY_ "CDECL",NULL},
|
||||
{KEY_ "STDCALL",NULL},
|
||||
|
||||
|
|
|
|||
|
|
@ -115,12 +115,6 @@
|
|||
/* We have libffi and can use it */
|
||||
#undef HAVE_LIBFFI
|
||||
|
||||
/* We have non-portable implementation of FFI calls */
|
||||
/* Only used as a last resort, when libffi is missin */
|
||||
#ifndef HAVE_LIBFFI
|
||||
#undef ECL_DYNAMIC_FFI
|
||||
#endif
|
||||
|
||||
/* We use hierarchical package names, like in Allegro CL */
|
||||
#undef ECL_RELATIVE_PACKAGE_NAMES
|
||||
|
||||
|
|
|
|||
|
|
@ -121,9 +121,6 @@ struct cl_env_struct {
|
|||
union ecl_ffi_values *ffi_values;
|
||||
union ecl_ffi_values **ffi_values_ptrs;
|
||||
#endif
|
||||
#ifdef ECL_DYNAMIC_FFI
|
||||
void *fficall;
|
||||
#endif
|
||||
|
||||
/* Alternative stack for processing signals */
|
||||
void *altstack;
|
||||
|
|
|
|||
|
|
@ -244,19 +244,6 @@ struct ecl_fficall {
|
|||
};
|
||||
|
||||
extern enum ecl_ffi_tag ecl_foreign_type_code(cl_object type);
|
||||
#ifdef ECL_DYNAMIC_FFI
|
||||
extern enum ecl_ffi_calling_convention ecl_foreign_cc_code(cl_object cc_type);
|
||||
extern void ecl_fficall_prepare(cl_object return_type, cl_object arg_types, cl_object cc_type);
|
||||
extern void ecl_fficall_push_bytes(void *data, size_t bytes);
|
||||
extern void ecl_fficall_push_int(int word);
|
||||
extern void ecl_fficall_align(int data);
|
||||
|
||||
extern struct ecl_fficall_reg *ecl_fficall_prepare_extra(struct ecl_fficall_reg *registers);
|
||||
extern void ecl_fficall_push_arg(union ecl_ffi_values *data, enum ecl_ffi_tag type);
|
||||
extern void ecl_fficall_execute(void *f_ptr, struct ecl_fficall *fficall, enum ecl_ffi_tag return_type);
|
||||
extern void ecl_dynamic_callback_call(cl_object callback_info, char* buffer);
|
||||
extern void* ecl_dynamic_callback_make(cl_object data, enum ecl_ffi_calling_convention cc_type);
|
||||
#endif
|
||||
|
||||
/* file.d */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue