Skip to content

Commit

Permalink
cs: support Android on 32-bit and 64-bit ARM
Browse files Browse the repository at this point in the history
Various configure and makefile improvements apply more broadly to
environments that, say, lack iconv or target 32-bit ARM without Thumb.
  • Loading branch information
mflatt committed Feb 7, 2021
1 parent 342bd66 commit 8a08704
Show file tree
Hide file tree
Showing 20 changed files with 167 additions and 63 deletions.
2 changes: 2 additions & 0 deletions racket/src/ChezScheme/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Supported platforms:
* OpenBSD: x86, x86_64
* NetBSD: x86, x86_64
* Solaris: x86, x86_64
* Android: ARMv7, AArch64
* iOS: AArch64

As a superset of the language described in the
[Revised<sup>6</sup> Report on the Algorithmic Language Scheme](http://www.r6rs.org)
Expand Down
2 changes: 1 addition & 1 deletion racket/src/ChezScheme/c/Mf-base
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Main=../boot/$m/main.$o
Scheme=../bin/$m/scheme

# CFLAGS is propagated separately:
SetConfigEnv = CC="${CC}" CPPFLAGS="${CPPFLAGS}" AR="${AR}" ARFLAGS="${ARFLAGS}"
SetConfigEnv = CC="${CC}" CPPFLAGS="${CPPFLAGS}" AR="${AR}" ARFLAGS="${ARFLAGS}" RANLIB="${RANLIB}"

# One of these sets is referenced in Mf-config to select between
# linking with kernel.o or libkernel.a
Expand Down
18 changes: 11 additions & 7 deletions racket/src/ChezScheme/c/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# define ACQUIRE_FENCE() __asm__ __volatile__ ("dmb ish" : : : "memory")
# define RELEASE_FENCE() ACQUIRE_FENCE()
#elif defined(__arm__)
# if arm_isa_version == 7
# if (arm_isa_version >= 7) || (__ARM_ARCH >= 7)
# define STORE_FENCE() __asm__ __volatile__ ("dmb ishst" : : : "memory")
# define ACQUIRE_FENCE() __asm__ __volatile__ ("dmb ish" : : : "memory")
# define RELEASE_FENCE() ACQUIRE_FENCE()
Expand Down Expand Up @@ -72,15 +72,18 @@ FORCEINLINE int CAS_STORE_RELEASE(volatile void *addr, void *old_val, void *new_
return ret;
}
#elif defined(__arm__)
FORCEINLINE int S_cas_any_fence(volatile void *addr, void *old_val, void *new_val) {
FORCEINLINE int S_cas_any_fence(int load_acquire, volatile void *addr, void *old_val, void *new_val) {
int ret;
__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5\n\t"
"mov %0, #0\n\t"
if (load_acquire)
ACQUIRE_FENCE();
else
RELEASE_FENCE();
__asm__ __volatile__ ("mov %0, #0\n\t"
"0:\n\t"
"ldrex r12, [%1, #0]\n\t"
"ldrex r12, [%1]\n\t"
"cmp r12, %2\n\t"
"bne 1f\n\t"
"strex r7, %3, [%1, #0]\n\t"
"strex r7, %3, [%1]\n\t"
"cmp r7, #0\n\t"
"bne 1f\n\t"
"it eq\n\t"
Expand All @@ -91,7 +94,8 @@ FORCEINLINE int S_cas_any_fence(volatile void *addr, void *old_val, void *new_va
: "cc", "memory", "r12", "r7");
return ret;
}
# define CAS_ANY_FENCE(a, old, new) S_cas_any_fence(a, old, new)
# define CAS_LOAD_ACQUIRE(a, old, new) S_cas_any_fence(1, a, old, new)
# define CAS_STORE_RELEASE(a, old, new) S_cas_any_fence(0, a, old, new)
#elif (__GNUC__ >= 5) || defined(__clang__)
# define CAS_ANY_FENCE(a, old, new) __sync_bool_compare_and_swap(a, old, new)
#elif defined(_MSC_VER)
Expand Down
7 changes: 6 additions & 1 deletion racket/src/ChezScheme/c/prim5.c
Original file line number Diff line number Diff line change
Expand Up @@ -2088,7 +2088,12 @@ static void s_free(uptr addr) {
}

#ifdef FEATURE_ICONV
#ifdef WIN32
#ifdef DISABLE_ICONV
# define iconv_t int
#define ICONV_OPEN(to, from) -1
#define ICONV(cd, in, inb, out, outb) -1
#define ICONV_CLOSE(cd) -1
#elif defined(WIN32)
typedef void *iconv_t;
typedef iconv_t (*iconv_open_ft)(const char *tocode, const char *fromcode);
typedef size_t (*iconv_ft)(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
Expand Down
10 changes: 8 additions & 2 deletions racket/src/ChezScheme/c/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ typedef char *memcpy_t;
#define MAKE_NAN(x) { x = 0.0; x = x / x; }
#define GETWD(x) getcwd((x),PATH_MAX)
typedef int tputsputcchar;
#define LOCKF
#ifndef __ANDROID__
# define LOCKF
#endif
#define DIRMARKERP(c) ((c) == '/')
#ifndef DISABLE_X11
# define LIBX11 "libX11.so"
Expand All @@ -149,6 +151,10 @@ typedef int tputsputcchar;
#define NSECCTIME(sb) (sb).st_ctim.tv_nsec
#define NSECMTIME(sb) (sb).st_mtim.tv_nsec
#define ICONV_INBUF_TYPE char **
#ifdef __ANDROID__
# define NOFILE 256
# define NO_USELOCALE
#endif
#define UNUSED __attribute__((__unused__))
#endif

Expand All @@ -175,7 +181,7 @@ typedef int tputsputcchar;
#define SECMTIME(sb) (sb).st_mtimespec.tv_sec
#define NSECATIME(sb) (sb).st_atimespec.tv_nsec
#define NSECCTIME(sb) (sb).st_ctimespec.tv_nsec
#define NSECMTIME(sb) (sb).st_mtimespec.tv_nsec
#define NSECM<TIME(sb) (sb).st_mtimespec.tv_nsec

This comment has been minimized.

Copy link
@Bogdanp

Bogdanp Feb 7, 2021

Contributor

@mflatt this looks like an unintended change.

This comment has been minimized.

Copy link
@mflatt

mflatt Feb 7, 2021

Author Member

Thanks!

#define ICONV_INBUF_TYPE char **
#define UNUSED __attribute__((__unused__))
#define USE_OSSP_UUID
Expand Down
26 changes: 22 additions & 4 deletions racket/src/ChezScheme/configure
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ installscriptname="scheme-script"
cflagsset=no
disablex11=no
disablecurses=no
disableiconv=no
addflags=yes
addwarningflags=no
default_warning_flags="-Wpointer-arith -Wall -Wextra -Werror -Wno-implicit-fallthrough"
Expand Down Expand Up @@ -273,6 +274,9 @@ while [ $# != 0 ] ; do
--disable-curses)
disablecurses=yes
;;
--disable-iconv)
disableiconv=yes
;;
--disable-auto-flags)
addflags=no
;;
Expand Down Expand Up @@ -420,6 +424,7 @@ if [ "$help" = "yes" ]; then
echo " --32|--64 specify 32/64-bit version ($bits)"
echo " --disable-x11 disable X11 support"
echo " --disable-curses disable [n]curses support"
echo " --disable-iconv disable iconv support"
echo " --disable-auto-flags no auto additions to CFLAGS/LDFLAGS/LIBS"
echo " --enable-warning-flags add GCC warning flags to CFLAGS"
echo " --libkernel build libkernel.a (the default)"
Expand Down Expand Up @@ -565,6 +570,13 @@ if [ "$disablecurses" = "yes" ]; then
ncursesLib=
fi

if [ "$disableiconv" = "yes" ]; then
iconvLib=
CPPFLAGS="${CPPFLAGS} -DDISABLE_ICONV"
else
iconvLib="-liconv"
fi

# Add automatic linking flags, unless suppressed by --disable-auto-flags
if [ "$addflags" = "yes" ] ; then
case "${flagsm}" in
Expand All @@ -586,22 +598,28 @@ if [ "$addflags" = "yes" ] ; then
LIBS="${LIBS} -lm -ldl ${ncursesLib} -lrt"
;;
*fb|*ob)
LIBS="${LIBS} -liconv -lm ${ncursesLib}"
LIBS="${LIBS} ${iconvLib} -lm ${ncursesLib}"
;;
*nb)
LIBS="${LIBS} /usr/lib/i18n/libiconv_std.a -lm /usr/pkg/lib/libncurses.a"
if [ "$disablecurses" = "no" ]; then
iconvLib="/usr/lib/i18n/libiconv_std.a"
fi
LIBS="${LIBS} ${iconvLib} -lm /usr/pkg/lib/libncurses.a"
;;
*s2)
LIBS="${LIBS} -lnsl -ldl -lm ${cursesLib} -lrt"
;;
*osx)
LIBS="${LIBS} -liconv -lm ${ncursesLib}"
LIBS="${LIBS} ${iconvLib} -lm ${ncursesLib}"
;;
*nt)
LIBS="${LIBS} -lshell32 -luser32 -lole32 -lrpcrt4 -luuid"
;;
8qnx)
LIBS="${LIBS} -lm /usr/local/lib/libiconv.so -lsocket ${ncursesLib}"
if [ "$disablecurses" = "no" ]; then
iconvLib="/usr/local/lib/libiconv.so"
fi
LIBS="${LIBS} -lm ${iconvLib} -lsocket ${ncursesLib}"
;;
esac
if [ "$threadLibs" != "" ] ; then
Expand Down
6 changes: 3 additions & 3 deletions racket/src/ChezScheme/s/mkheader.ss
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@
(nl)
(pr "#define SPINLOCK(addr) \\~%")
(pr " __asm__ __volatile__ (\"0:\\n\\t\"\\~%")
(pr " \"ldrex r12, [%0, #0]\\n\\t\"\\~%")
(pr " \"ldrex r12, [%0]\\n\\t\"\\~%")
(pr " \"cmp r12, #0\\n\\t\"\\~%")
(pr " \"bne 1f\\n\\t\"\\~%")
(pr " \"mov r12, #1\\n\\t\"\\~%")
Expand Down Expand Up @@ -763,7 +763,7 @@
(pr "#define LOCKED_INCR(addr, ret) \\~%")
(pr " __asm__ __volatile__ (\"mov %0, #0\\n\\t\"\\~%")
(pr " \"0:\\n\\t\"\\~%")
(pr " \"ldrex r12, [%1, #0]\\n\\t\"\\~%")
(pr " \"ldrex r12, [%1]\\n\\t\"\\~%")
(pr " \"add r12, r12, #1\\n\\t\"\\~%")
(pr " \"strex r7, r12, [%1]\\n\\t\"\\~%")
(pr " \"cmp r7, #0\\n\\t\"\\~%")
Expand All @@ -779,7 +779,7 @@
(pr "#define LOCKED_DECR(addr, ret) \\~%")
(pr " __asm__ __volatile__ (\"mov %0, #0\\n\\t\"\\~%")
(pr " \"0:\\n\\t\"\\~%")
(pr " \"ldrex r12, [%1, #0]\\n\\t\"\\~%")
(pr " \"ldrex r12, [%1]\\n\\t\"\\~%")
(pr " \"sub r12, r12, #1\\n\\t\"\\~%")
(pr " \"strex r7, r12, [%1]\\n\\t\"\\~%")
(pr " \"cmp r7, #0\\n\\t\"\\~%")
Expand Down
2 changes: 1 addition & 1 deletion racket/src/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ no-local-racket:
@RUN_LOCAL_RACKET@:
mkdir -p local
$(MAKE) local/Makefile
cd local && $(MAKE)
cd local && $(MAKE) @LOCAL_RACKET_TARGET@

local/Makefile:
cd local && `cd ..; cd $(srcdir); pwd`/configure --disable-gracket @CONFIGURE_LOCAL_RACKET@
Expand Down
76 changes: 47 additions & 29 deletions racket/src/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -371,66 +371,84 @@ Some less commonly needed `configure` flags are for Racket BC:
Cross-compiling for Android
========================================================================

[Currently, cross-compilation for Android works only for the Racket BC
implementation.]

As an example of cross-compiling, to compile for Android on ARM using
the NDK, use (all on one line)
As an example of cross-compiling Racket for Android on ARMv7 using the
NDK, use (all on one line)

configure --host=arm-linux-androideabi
--enable-sysroot="[ndk]/platforms/android-[N]/arch-arm"
--enable-sysroot="[sysroot]"
--enable-racket=auto

where [ndk] is the path to the installed NDK, [N] is a target version
of Android (such as 14), and
If you use the NDK script "make-standalone-toolchain.sh" to generate a
toolchain directory, then include that directory's "bin" in your PATH
(so that `arm-linux-androideabi-gcc`, etc., are found), and you can
omit `--enable-sysroot` (or specify [sysroot] as the toolchain
directory's "sysroot" subdirectory).

In other NDK configurations, you may have

[ndk]/toolchains/arm-linux-androideabi-[comp]/prebuilt/[platform]/bin

is in your PATH (so that a suitable `gcc`, `ar`, etc., are found) for
the [comp] of your choice and the [platform] used to compile.
in your PATH (so that `arm-linux-androideabi-gcc`, etc., are found)
where [ndk] is the path to the installed NDK and for the [comp] of
your choice and the [platform] used to compile, and then [sysroot] is

[ndk]/platforms/android-[N]/arch-arm

where [N] is a target version of Android (such as 14).

For 64-bit ARM, replace "arm" above with "aarch64", and replace
"androideabi" with "android".

When building BC, you may need to add `--disable-cify` for 32-bit ARM
and `--enable-cify` for 64-bit ARM instead of inheriting the build
machine's disposition.


========================================================================
Cross-compiling for iOS
========================================================================

To compile the Racket BC runtime system as a Framework for iOS, use
(all on one line)
To compile the Racket runtime system as a Framework for iOS, use (all
on one line)

configure --host=[arch]-apple-darwin
--enable-ios="[sdk]"
--enable-racket=racket
--enable-bcdefault
--enable-racket=auto

where [arch] is one of

- armv7, armv7s, or aarch64: to run on iOS
- i386 or x86_64: to run on the simulator
- x86_64 or aarch64: to run on the simulator

The [sdk] argument is a path to an iOS SDK, but if it is "iPhoneOS" or
"iPhoneSimulator", then the corresponding SDK is located in the
standard place within the XCode application. For example, "iPhoneOS"
becomes the path (all on one line)
The [sdk] argument is a path to an iOS SDK for "iPhoneOS" or
"iPhoneSimulator". The corresponding SDK is located in the standard
place within the XCode application. For example, "iPhoneOS" becomes
the path (all on one line)

/Applications/Xcode.app/Contents/Developer/Platforms/
iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk

To cross-compile for CS, you must supply the Chez Scheme compiler that
Racket CS was built with. Assuming you have built Racket CS for your
machine at "/path/to/racket" using the default `make` target, you can
configure the cross build using that Racket binary and a path to the
Chez Scheme build folder as follows (all on one line)
To use an existing Racket build for the build platform using
`--enable-racket`, be sure to include `--enable-scheme` for Racket CS.
For example, if you have built Racket CS for your machine at
"/path/to/racket" using the default `make` target, you can configure
the cross build using that Racket binary and a path to the Chez Scheme
build folder as follows (all on one line)

configure --host=[arch]-apple-darwin
--enable-ios="[sdk]"
--enable-racket=/path/to/racket/bin/racket
--enable-scheme=/path/to/racket/src/build/cs/c

Currently, iOS enforces strict W^X protection on memory pages. See the
note about "writes to `space_code` memory" in "ChezScheme/c/segment.c"
for the implications this has on Racket CS. In principle, if you avoid
passing newly-allocated code between threads and avoid `#:blocking?`
foreign callbacks, you should not run into any issues.
Currently, iOS enforces W^X protection on memory pages, which is
technically a problem for Racket CS. See the note about "writes to
`space_code` memory" in "ChezScheme/c/segment.c" for the implications.
If you avoid passing newly-allocated code between threads and avoid
`#:blocking?` foreign callbacks, you might not run into any issues.

When building BC for iOS, you may need to add `--disable-cify` for
32-bit target and `--enable-cify` for 64-bit target instead of
inheriting the build machine's disposition.


========================================================================
Expand Down
2 changes: 2 additions & 0 deletions racket/src/bc/configure-parent.ac
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ if test "${enable_racket}" = "auto" ; then
fi
RUN_LOCAL_RACKET="local/bc/racket3m"
CONFIGURE_LOCAL_RACKET=--enable-bc
LOCAL_RACKET_TARGET=bc

if test "${enable_cgcdefault}" = "yes" ; then
MAIN_VARIANT=cgc
Expand All @@ -62,6 +63,7 @@ AC_SUBST(RUN_RACKET)
AC_SUBST(MAKE_LOCAL_RACKET)
AC_SUBST(RUN_LOCAL_RACKET)
AC_SUBST(CONFIGURE_LOCAL_RACKET)
AC_SUBST(LOCAL_RACKET_TARGET)

makefiles="Makefile"

Expand Down
3 changes: 3 additions & 0 deletions racket/src/cfg-bc
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ ac_unique_file="setup-go.rkt"
enable_option_checking=no
ac_subst_vars='LTLIBOBJS
LIBOBJS
LOCAL_RACKET_TARGET
CONFIGURE_LOCAL_RACKET
RUN_LOCAL_RACKET
RUN_RACKET
Expand Down Expand Up @@ -2330,6 +2331,7 @@ if test "${enable_racket}" = "auto" ; then
fi
RUN_LOCAL_RACKET="local/bc/racket3m"
CONFIGURE_LOCAL_RACKET=--enable-bc
LOCAL_RACKET_TARGET=bc
if test "${enable_cgcdefault}" = "yes" ; then
MAIN_VARIANT=cgc
Expand All @@ -2353,6 +2355,7 @@ fi
makefiles="Makefile"
ac_config_files="$ac_config_files $makefiles"
Expand Down
3 changes: 3 additions & 0 deletions racket/src/cfg-cs
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ ac_unique_file="setup-go.rkt"
enable_option_checking=no
ac_subst_vars='LTLIBOBJS
LIBOBJS
LOCAL_RACKET_TARGET
CONFIGURE_LOCAL_RACKET
RUN_LOCAL_RACKET
RUN_RACKET
Expand Down Expand Up @@ -2239,6 +2240,7 @@ if test "${enable_racket}" = "auto" ; then
fi
RUN_LOCAL_RACKET="local/cs/c/racketcs"
CONFIGURE_LOCAL_RACKET=--enable-cs
LOCAL_RACKET_TARGET=cs
# If BC is the default, then we rely on BC configure-parent
# being used instead of this one:
Expand All @@ -2256,6 +2258,7 @@ fi
makefiles="Makefile"
ac_config_files="$ac_config_files $makefiles"
Expand Down

0 comments on commit 8a08704

Please sign in to comment.