Please review my patch to make GHC calling convention work on ARM

All,

I would like to submit the attached patch, which allows the GHC (Glasgow Haskell Compiler) calling convention to work on ARM targets.

Could some nice person please review this code, so I can move towards getting it committed?

I have thoroughly tested this patch again GHC on a Debian-ARM (armel) system. Unfortunately my understanding of LLVM is limited, so it's likely I'm not doing things the best way.

Some explanation:
In the GHC calling convention, all calls are "tail calls" (really just jumps) and there is no returning. The meanings of the registers are determined by the GHC compiler. GHC calling convention code must not touch the stack pointer, because that's used to preserve the state for our return to C-land. Jumps between C and GHC are implemented directly in assembly language so LLVM doesn't have to deal with them.

So, I disabled the generation of prologues and epilogues, and I found that I also needed to tell it that there are no callee-saves registers in the GHC calling convention.

Thanks very much and keep up the excellent work, everyone!

Steve

llvm.patch (4.27 KB)

Hi Steve,

I'm not an LLVM developer but am the author/maintainer of the LLVM
backend in GHC.

The patch looks mostly good to me (although I am not that familiar
with ARM so could easily have missed something). My main concern is
why are you avoiding using the R0 - R3 registers?

Also, could you please update me on the status of this work. I assume
you are getting GHC running in registerised mode on ARM. There is also
a guy called Karel Gardas (karel.gardas@centrum.cz) who is working on
this as well and making good progress. Would be good (off this mailing
list though) to all get in contact.

Cheers,
David

David,

Thanks for that - I emailed Karel Gardas. I've got GHC successfully registerised on ARM, and I'm just starting on pushing it upstream.

The reason why I'm avoiding the R0-R3 registers is mainly because my qemu-based ARM VM takes days to compile everything, and I was being conservative. The GHC code can call directly out to C, so it would need to save its own R0-R3 when it does that. I know GHC can do this, presumably efficiently (using the caller-saves registers last) so I'm sure it's better to do that. Perhaps you can advise me.

I was planning on looking into this later, but if you think it's better to do it once and do it right, then let me know and I'll sort that out.

Another thing I'd like to improve later is the 'bx lr' (return) instruction at the end of a GHC 'function', which is never reached, so we should really not generate it.

Steve

David,

Thanks for that - I emailed Karel Gardas. I've got GHC successfully
registerised on ARM, and I'm just starting on pushing it upstream.

Great!

The reason why I'm avoiding the R0-R3 registers is mainly because my
qemu-based ARM VM takes days to compile everything, and I was being
conservative. The GHC code can call directly out to C, so it would need to
save its own R0-R3 when it does that. I know GHC can do this, presumably
efficiently (using the caller-saves registers last) so I'm sure it's better
to do that. Perhaps you can advise me.

I was planning on looking into this later, but if you think it's better to
do it once and do it right, then let me know and I'll sort that out.

Yes I think its better to sort out now. I would advise you use R0 -
R3. Also, try to put the more import GHC virtual registers (Base, Sp,
Hp, R1, SpLim) into callee save registers and put the less import R2 -
R8 registers into caller save.

You probably know that the place in GHC to modify is
'includes/stg/MachRegs.h' and use a CPP defines like '#define
CALLER_SAVES_R3' to indicate which registers GHC needs to save across
C calls.

Cheers,
David