-
Notifications
You must be signed in to change notification settings - Fork 104
ARM64 port draft milestones
An ARM64 port will take at the very least 3 to 4 months. This claim is based on past estimates from Gary Byers, who is a genius programmer and more familiar with the implementation of CCL than anyone. Less wizardly programmers will necessarily require more time.
Much will be taken from PPC-64, but will there be changes? It should at least be written down.
- Tagging system
- Register conventions
- Stack layout
- Calling conventions
- Something about tail-call optimization?
- Something about unwind-protect?
- Something about atomic code & interruptibility?
This will involve a fair amount of work, including
- Implementing the assembler and disassembler
- Writing LAP (assembly) code to implement bignums and other functionality as found in ccl:level-0;ARCH; (where ARCH is ARM, X86, etc.)
- Writing ARM64 vinsns (assembly language templates) for use by the compiler backend
- Implement lisp-called subprimitive routines and other runtime support in the lisp kernel (about 10,000 lines of assembly)
- Understand the ARM64 C ABI and implement support for calling external C code from CCL
- Update and enhance our new libclang-based ffigen to create the
.cdb
files comprising the interface database (as used by the#_
reader macro).
There will not be much visible progress at this stage, except for a lot of commits. This step is likely to take an easy 6 to 8 weeks on its own.
When the 32-bit ARM port was coming up, this was an early milestone. A 64-bit ARM port will need a similar one.
(let* ((*target-backend* (find-backend :linuxarm)))
(%define-arm-lap-function
'fact
'((let ((n arg_z))
(check-nargs 1)
l0
(cmp n ($ 0))
(moveq arg_z '1)
(bxeq lr)
(build-lisp-frame imm0)
(vpush1 arg_z)
(sub arg_z arg_z '1)
(bl l0)
(vpop1 arg_y)
(restore-lisp-frame imm0)
(mov pc
($ (arm-subprimitive-address '.spbuiltin-times)))))))
#<XFUNCTION #xCFBEC6E>
? (uvref * 1)
#<XCODE-VECTOR #xCFBEC2E>
? (dotimes (i (uvsize *)) (format t "~&~d: #x~8,'0x" i (uvref * i)))
0: #xE3502004
1: #x17F001F0
2: #xE3504000
3: #x03A04004
4: #x012FFF1E
5: #xE3A00013
6: #xE92D4C01
7: #xE52A4004
8: #xE2444004
9: #xEBFFFFF7
10: #xE49A5004
11: #xE8BD4C01
12: #xE3A0FCA5
13: #x00000000
14: #x0000003C
NIL
?
Produce reasonable-looking results from examples like
(arm64-xcompile-lambda '(lambda () (+ 2 2)) :show-vinsns t)
(arm64-xcompile-lambda '(lambda (x) (prin1 (+ x 2))) :show-vinsns t)
;; demonstrate inline consing
(arm64-xcompile-lambda '(lambda (x y)
(let ((q (float (+ x y)))
(c (cons x y)))
(when (zerop q)
(format t "yow!"))
(vector x y q c))) :show-vinsns t)
All .lisp
files can be compiled to ARM64 fasls. This implies that there is an ARM64 backend (and file compiler) that is complete enough to compile the lisp sources. While it’s obviously desirable for the compiled code to be correct as possible, there’s no practical way to test this at this stage.
There is an ARM64 lisp kernel and bootstrapping image that can find and call the initial function in that image (namely, the value of %toplevel-function
in ccl:level-0;nfasload.lisp). This demonstrates that there is a bootstrapping lisp image, and enough of a lisp kernel to map the image into memory and start executing lisp code.
The file l1-streams is the first thing in the loading sequence that makes significant use of CLOS, and a very high percentage of all the basic functionality in the lisp has to work to get to that point.
The ARM64 lisp can re-compile itself.
- see: https://github.com/Clozure/ccl-tests and https://github.com/sbcl/sbcl/tree/master/tests
- Test framework for correct execution of Common Lisp and the CCL extensions
- Execute selected programs to test their working
- Stability tests for garbage collection, memory management, threads, error handling, I/O, image saving/restarting, ...
- Performance tests to identify bottlenecks