Clang support - z88dk/z88dk GitHub Wiki

[!WARNING]
Clang support is experimental, your experience and satisfaction may vary.

z88dk supports 3 different compilers as code generators. Each compiler has different strengths and features thus it's not trivial to say which compiler is recommended. The characteristics of sccz80 and sdcc have and are discussed elsewhere.

CPU support

One factor in choosing which compiler to use, is what CPU is being targeted. Unfortunately not all compilers support all the CPUs supported by z88dk.

CPU sccz80 sdcc ez80-clang
8080 :white_check_mark: :x: :x:
8085 :white_check_mark: :x: :x:
gbz80 :white_check_mark: :white_check_mark: :x:
z80 :white_check_mark: :white_check_mark: :white_check_mark:
z80n :white_check_mark: :white_check_mark: :white_check_mark:(1)
z180 :white_check_mark: :white_check_mark: :white_check_mark:
ez80_z80 :white_check_mark: :white_check_mark: :white_check_mark:(2)
r2ka :white_check_mark: :white_check_mark: :x:
r3k :white_check_mark: :white_check_mark: :x:
r4k :white_check_mark:(3) :white_check_mark:(3) :x:

(1) Compiles to z80 code only and doesn't take benefit of added instructions

(2) Only takes limited benefit of added instructions

(3) Generates r2ka/r3ka compatible code and assembles for r4k

Selecting which compiler to use

With the classic library, selecting which compiler to use is a command line switch -compiler=sccz80, -compiler=sdcc, -compiler=ez80clang.

Clang

Downloading and installing ez80-clang

The z88dk project doesn't make any modifications to clang, so download it from the upstream project: https://github.com/jacobly0/llvm-project/wiki and copy ez80-clang[.exe] into z88dk/bin.

Code generation characteristics

The code generated by ez80-clang makes extensive use of both index registers (and index halves) and as such is not suitable for generating code that is intended to run on targets that reserve either of the index registers. For example the generated code would probably cause a ZX81 to crash very quickly.

Code generation using clang is very quick and the generated code sometimes bears little relation to the input - for example loops may be aggressively optimised away. This can result in larger code than that generated by the other two compilers.

The code generated for operations involving 32 bit integer values is not particularly optimal in either size or speed. For example the classic md5 algorithm used as part of the autotests is both significantly larger and over twice as slow as the other compilers.

On the other hand, running the enigma example (which uses int8 and int16 types) generates code of comparable size and executes in about 50% of the time of the other compilers.

Calling convention

Clang broadly uses the __stdc calling convention with a small modification to the 8 bit return register:

Parameter size (bytes) Stack size (bytes) Return registers
1 2 a
2 2 hl
4 4 dehl
8 8 iybcdehl

The __smallc, __z88dk_callee, __z88dk_fastcall or any other calling conventions provided by z88dk are not supported.

This calling convention has, somewhat surprisingly, proven to more compatible with the classic library (where for historical reasons 8 bit return values and parameters have been avoided) than newlib. Compatibility with classic is achieved by using an macro (__ZPROTOx) that creates an inline function prototype with the parameters reversed. This does not create any additional overhead, except when the address of the function is taken as a function pointer.

Library support

Not all of classic has been exported to clang yet. However most applications just using the C standard library should work. If you need a function, check the header files, if takes multiple arguments it will be defined using __ZPROTOx when it's been exported to clang. Should something you need not be available raise in the forum or here with an Issue.