Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(zcc) Support using ez80-clang as compiler #2329

Open
15 of 20 tasks
suborb opened this issue Jun 26, 2023 · 6 comments
Open
15 of 20 tasks

(zcc) Support using ez80-clang as compiler #2329

suborb opened this issue Jun 26, 2023 · 6 comments

Comments

@suborb
Copy link
Member

suborb commented Jun 26, 2023

The branch ez80_clang provides support for -compiler=ez80clang - hello world works perfectly!

Support routines are starting to be written, there's a few of them: https://github.com/jacobly0/llvm-project/blob/6c61664110f888c0285ae4c48b150c9a7a4361bb/llvm/lib/Target/Z80/Z80ISelLowering.cpp

Notes:

  • The generated code uses both index registers so not particularly friendly for a lot of our targets
  • Index halves are also used by the code generator (there may be a flag to sort this out) add -target-feature -idxhalf -triple z180
  • The support routines have a few different calling conventions
  • Calling convention is broadly __stdc so classic is actually easier to get running than newlib (due to the 8 bit parameter handling difference between sdcc and clang)

Tasklist:

  • Define sys/proto.h to do the prototyping magic macros mentioned below
  • Define and use __STDC_ABI_ONLY macro to hide away __z88dk_callee and __z88dk_fastcall macro mappings
  • Update header files to use sys/proto.h
  • Nobble sccz80 so it generates clang entry points as well as sccz80 and sdcc ones
  • Refactor ctype.h to export a non-fastcall entry point
  • Implement bits of librt (support routines) as we come across them
  • Update zcc to use a CPU mapping (so z180 targets can join in the fun)
  • Ensure stdio.h, string.h, ctype.h are compatible
  • Ensure fcntl.h is compatible (involves an extra export in all target fcntl funds)
  • Ensure stdlib.h is compatible
  • Only support math32, so update multi-parameter endpoints
  • math32 librt support
  • Update graphics.h + library exports
  • games.h
  • psg/ay
  • Misc small features (assert, debug, setjmp)
  • Get some test suites running (not in CI)
  • Update compression routines (they may not even be good for sdcc?)
  • Target libraries
  • Create rules for KC160 ((toolchain) Add support for KC160 (KL5C160xxx) #2402) - I have a feeling it will be good match if we pick the z180 triplet and fix up frame access. z180 triplet uses iyh/iyl
@suborb
Copy link
Member Author

suborb commented Jun 27, 2023

A little more progress:

% zcc +cpm -clib=ez80clang_ix  -v enigma.c -create-app -DARGC -m
%  ls -al A.COM
-rw-r--r--  1 dom  staff  4308 27 Jun 21:46 A.COM
% z88dk-ticks -x a.map  A.COM -- helloeveryone
RXSEC MSXCH FFL
246964

The generated code is quite chunky (lots of index registers) but the llvm optimiser does seem to make things a fair bit quicker. So it's a nice compromise. Compilation speed is nice and speedy as well.

@desertkun
Copy link
Collaborator

What does that mean in context of debugging? In comparison to gdbserver stubs etc?

@suborb
Copy link
Member Author

suborb commented Jun 27, 2023

It's a good question that at the moment I've not thought too much about - I'm just tinkering and trying to come up with a way to handle __smallc code without too much disruption.

It looks like there's always a frame pointer, so walking the function call tree should be possible. It does look like DWARF information can be output, though of course we don't do anything with that and the gas style directives will cause a few problems

@suborb
Copy link
Member Author

suborb commented Jun 28, 2023

I'm still bashing my head a little with __smallc. I've got something working (even with function pointers), but it's not wonderfully pretty. Let's assume for every library function func we have the following entry points:

  • func - sccz80
  • _func - sdcc
  • ___func clang (there's some library routines which already are _func and _func_ so need to make it a bit more unique

The clang variant has the prototype arguments reversed but is otherwise the same code.

extern char *__strcpy(char *d, char *s);

__attribute__((always_inline))
static inline char *strcpy(char *s, char *d)
        __attribute__((overloadable))
        __attribute__((enable_if(1, ""))) {
        return __strcpy(d,s);
}


extern void func2(void (*func)());

void func(char *s)
{
   char *(*blah)();
   char buf[80];
   strcpy(s,buf);
   blah = strcpy;
   func2(blah);
}

Generates:

        public  _func                           ; -- Begin function func
_func:                                  ; @func
; %bb.0:                                ; %entry
        ld      iy, 0
        add     iy, sp
        ld      hl, -82
        add     hl, sp
        ld      sp, hl
        ld      l, (iy + 2)
        ld      h, (iy + 3)
        push    iy
        ld      bc, -82
        add     iy, bc
        ld      e, iyl
        ld      d, iyh
        pop     iy
        push    hl
        push    de
        call    _strcpy_
        ld      hl, 86
        add     hl, sp
        ld      sp, hl
        ret

Uncommenting the call to func2 yields:

        call    _strcpy_
        pop     hl
        pop     hl
        ld      hl, __ZL6strcpyUa9enable_ifILi1EEPcS_
        push    hl
        call    _func2
        ld      sp, ix
        pop     ix
        ret
        SECTION code_compiler
                                        ; -- End function
        SECTION code_compiler
__ZL6strcpyUa9enable_ifILi1EEPcS_:      ; @_ZL6strcpyUa9enable_ifILi1EEPcS_
; %bb.0:                                ; %entry
        ld      iy, 0
        add     iy, sp
        ld      l, (iy + 2)
        ld      h, (iy + 3)
        ld      e, (iy + 4)
        ld      d, (iy + 5)
        ld      (iy + 2), e
        ld      (iy + 3), d
        ld      (iy + 4), l
        ld      (iy + 5), h
        jp      _strcpy_

So we can see that the inline definition has been added to the local source. Given that I don't think pointers to library functions are used that much it's probably liveable with.

The extra exporting within libsrc/ can probably be handled with a judicious search/replace for .asm and sccz80 compiled code can just additionally export the other entry point.

Which just leaves a mammoth job in the headers which might be do-able with some appropriate macros. There's already quite a large task to hide all the __z88dk_callee macros.

The alternative is switching the whole library to __stdc which will be massively error-prone.

@suborb
Copy link
Member Author

suborb commented Jun 28, 2023

Lovely:

#if __SCCZ80
#define FUNC2(r,p, n,t1,a1,t2,a2) extern r __LIB__ p n(t1 a1,t2 a2) __smallc;
#elif __SDCC
#define FUNC2(r,p, n,t1,a1,t2,a2) extern r p n(t1 a1,t2 a2) __smallc;
#else
#define FUNC2(r,p, n,t1, a1,t2, a2) extern r p n##_  (t2 a2,t1 a1); \
  __attribute__((always_inline)) \
  static inline r p n(t1 a1,t2 a2) \
        __attribute__((overloadable)) \
        __attribute__((enable_if(1, ""))) { \
        return n##_  (a2,a1); \
  }
#endif


FUNC2(char,*, strcpy, char *,d, char *,s)

Which is starting to look a bit like the header generation m4 in newlib.

@suborb
Copy link
Member Author

suborb commented Jun 29, 2023

Ah , edge conditions. I've forgotten if there is a correct behaviour, or if it's undefined. sccz80 keeps the sign bit whilst shifting. sdcc doesn't and clang, well it depends (as below). The sccz80 behaviour matches that of the compiler support routines.

signed long func()
{
        long l = 0x80000000;
        return  l >> 1;
}

signed long func2()
{
        return 0x80000000 >> 1;
}
_func:                                  ; @func
; %bb.0:                                ; %entry
        ld      hl, 0
        ld      de, -16384
        ret
        SECTION code_compiler
                                        ; -- End function
        SECTION code_compiler
        public  _func2                          ; -- Begin function func2
_func2:                                 ; @func2
; %bb.0:                                ; %entry
        ld      hl, 0
        ld      de, 16384
        ret

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants