This file presents
* a list of platforms CLISP is known to run on,
* special hints for some platforms,
* hints for porting to new platforms.


List of platforms
==================

* GNU and Unix platforms
* macOS
* Windows (both native Windows and Cygwin)


Special hints for some platforms
================================


* On Nokia N800 (Arm) running Linux:

If you get a crash during loading of the first few lisp file (first GC),
add "-DNO_GENERATIONAL_GC" to CFLAGS.
If your modules do not work (clisp.h does not define "object" type),
install GNU sed.


* On ppc and ppc64 running Linux:

If you get a crash during loading of the first few lisp file (first GC),
add "-DNO_GENERATIONAL_GC" to CFLAGS.


Porting to new platforms
========================

The C compiler
--------------

Choose a reliable C compiler. GNU gcc is a good bet. Generally, start the
port with the least optimization settings regarding the compiler (-O0 in
the CFLAGS) and the safest optimization settings regarding the CLISP source
(configure with --enable-portability).

Address space layout
--------------------

Generally (except on 32-bit machines when configured with --enable-portability)
CLISP tries to use memory mapping facilities (mmap on Unix, VirtualAlloc on
Windows) in order to
  - simplify memory management (a large block of memory is more efficient
    to manage that a set of randomly distributed memory pages),
    cf. macro SPVW_BLOCKS vs. SPVW_PAGES,
  - support generational garbage collection,
    cf. macro GENERATIONAL_GC,
  - speed up type recognition by putting type tags into the pointers,
    cf. macro TYPECODES vs. HEAPCODES.

Such memory mapping requires knowledge about the address space layout.
The configuration determines some parameters about the address space layout,
such as:
  checking for the code address range... 0x00000000
  checking for the malloc address range... 0x01000000
  checking for the shared library address range... 0xB6000000
  checking for the stack address range... 0xBE000000

If you need a deeper understanding of the address space layout, the following
tools print a memory map (i.e. the virtual memory areas) of a running process:
  * The '-mm' option: Run
      $ ./lisp.run -mm
    This option works on many, but not all platforms.
  * OS dependent tools: Run an executable, look up its process ID (through "ps"),
    then:
    - On Linux:
      $ cat /proc/$pid/maps
      $ pmap $pid
    - On Mac OS X:
      $ vmmap -interleaved $pid
    - On FreeBSD:
      $ cat /proc/$pid/map
      $ procstat -v $pid
    - On NetBSD:
      $ cat /proc/$pid/map
    - On OpenBSD:
      # procmap -p $pid
    - On AIX:
      $ procmap -S $pid
    - On Solaris:
      $ pmap $pid

The stack address range is printed by these tools, but CLISP does not make
assumptions about it.

Verifying that all supported configurations work
------------------------------------------------

There are a number of configurations of the memory management (different
object representation, different GC algorithms, old_gc vs. multithread_gc,
etc.). It is useful to verify that all such supported configurations work
and which configuration cannot be supported on the particular platform,
so that
  - you get an overview of which features don't work in any configuration
    (you can then disable this feature in lispbibl.d),
  - you can be sure that there are no hidden bugs lurking,
  - later regressions become apparent quickly.

To do so:
1) Get at least one configuration to at least build lisp.run without
   compilation errors (--enable-portability is your best bet for this).
   Then get an understanding of address space layout (see above).
2) Add to lispbibl.d platform dependent sections:
   - A section that defines MAPPABLE_ADDRESS_RANGE_START and
     MAPPABLE_ADDRESS_RANGE_END.
   - A section that defines the parameters for SINGLEMAP_MEMORY:
     SINGLEMAP_ADDRESS_BASE, SINGLEMAP_TYPE_MASK, SINGLEMAP_oint_type_shift.
   - A section that defines the parameters for ONE_FREE_BIT_HEAPCODES:
     garcol_bit_o.
   - A section that defines the parameters for TYPECODES_WITH_TRIVIALMAP.
   - A section that defines the parameters for TYPECODES_WITH_MALLOC.
3) Build the whole set of variants.
   This is done through one of the commands
     make -k -f Makefile.devel multibuild-porting32-gcc
     make -k -f Makefile.devel multibuild-porting32-cc
     make -k -f Makefile.devel multibuild-porting64-gcc
     make -k -f Makefile.devel multibuild-porting64-cc
   Pick the one that matches your platform bitness (32-bit or 64-bit
   platform) and your compiler (GCC or compatible, e.g. clang, versus
   vendor cc).
   Before doing this, you need to set an environment variable
   MULTIBUILD_32_OPTIONS (for the 32-bit target) or MULTIBUILD_64_OPTIONS
   (for the 64-bit target), that contain configuration options, typically
   --prefix, --with-libsigsegv-prefix, --with-libffcall-prefix options.
4) Depending on the results, define *_WORKS macros in lispbibl.d:
   - SINGLEMAP_WORKS, depending on the result of
     build-porting*-spvw_pure_blocks
   - HEAPCODES1BIT_WITH_TRIVIALMAP_WORKS, depending on the result of
     build-porting*-one_free_bit_heapcodes-trivialmap
   - HEAPCODES1BIT_WITH_MALLOC_WORKS, depending on the result of
     build-porting*-one_free_bit_heapcodes-malloc
   - KERNELVOID32_HEAPCODES_WORKS, depending on the result of
     build-porting32-*-kernelvoid32_heapcodes
   - GENERIC64C_HEAPCODES_WORKS, depending on the result of
     build-porting64-*-generic64_heapcodes
   - TYPECODES_WITH_TRIVIALMAP_WORKS, depending on the result of
     build-porting*-typecodes-spvw_mixed_blocks-trivialmap
   - TYPECODES_WITH_MALLOC_WORKS, depending on the result of
     build-porting64-gcc-typecodes-spvw_pure_pages
     build-porting64-gcc-typecodes-spvw_mixed_pages
     build-porting64-gcc-typecodes-spvw_mixed_blocks-malloc
5) Redo step 3.
   Inspect all the build-porting*/cbcstep3.log and determine which failures
   were justified and which were bugs that you can fix.
   If you could fix bugs, repeat this step.
6) Add to Makefile.devel a target multibuild-<platform> that contains all
   configuration targets that should succeed.
7) Run "make -k -f Makefile.devel multibuild-<platform>" and verify that
   build-porting*/cbcstep3.log succeeded.

Enabling optimizations that work
--------------------------------

After you have performed "Verifying that all supported configurations work"
(see above):
1) In makemake.in add a section with platform dependent configuration flags.
   You can start with the flags that get enabled when ${enable_portability}
   is 'yes'.
2) Remove at many de-optimization flags from this section as you can.
   Then run
     $ rm -rf build-porting*
     $ make -k -f Makefile.devel multibuild-<platform>
   If not all these builds succeeded (look at build-porting*/cbcstep3.log
   again), re-enable some de-optimization flags and repeat this step.

Quick porting
-------------

If you don't want to go through the (lengthy) process described in the sections
above, you can alternatively make some educated guess about which configuration
will likely work out. Here are tips for this approach.

On 64-bit platforms, if you cannot identify a pattern for the address space
layout, add -DGENERIC64_HEAPCODES -falign-functions=8 to the CFLAGS.

If you get an error message concerning mapped memory, you should add
-DNO_SINGLEMAP to the CFLAGS and recompile. Doing so introduces a tiny speed
penalty. If you still get an error message concerning mapped memory, you
should add -DNO_TRIVIALMAP to the CFLAGS and recompile.

Other troubleshooting
---------------------

Some options or optimizations are enabled through macros, conditionally
defined in lispbibl.d. You can check which macros get defined in lispbibl.d
by looking into lispbibl.h, assuming you are using gcc. For example:
    make lispbibl.h
    grep TYPECODES lispbibl.h

If you get an error message mentioning "handle_fault", then generational GC
is not working. Add -DNO_GENERATIONAL_GC to the CFLAGS and recompile.

If you get an error message during the loading of the first 10 Lisp files,
during the construction of the first .mem file, check the choice of
setjmp/longjmp functions in lispbibl.d.

If interpreted.mem was successfully generated, but lisp.run dumps core when
loading .fas files, you should add -DSAFETY=3 to the CFLAGS and recompile.
Find out which is the least SAFETY level that produces a working lisp.run and
lispinit.mem, and tell me about it.

