LLVM on small MCUs?

It is really cool that LLVM has a backend for PIC now. I wonder if someone could comment on the suitability of LLVM for 8-bit and 16-bit MCUs? Is there significant impedance mismatch or is it relatively easy to get good object code for these platforms? (I.e. roughly comparable to gcc4?)

I ask since gcc is causing significant pain for one of my students. He could switch over to LLVM but only after writing a backend for AVR (8-bit RISC).

Thanks,

John Regehr

John Regehr wrote:

I ask since gcc is causing significant pain for one of my students. He could switch over to LLVM but only after writing a backend for AVR (8-bit RISC).

An AVR backend would be very cool. AVR is way more compiler
friendly than PIC, so it should not be all that difficult
either.

The only hitch is that in the MCU world people expect to be
able to write interrupt handlers and the like in C, so one
needs to invent a way to express them in LLVM. Inventive
use of #define and some asm may be all that is needed, though.

Most of the support that I have seen for this in other compilers amounts
to custom calling conventions and preambles. Are you thinking of more
than this?

Most of the support that I have seen for this in other compilers amounts
to custom calling conventions and preambles. Are you thinking of more
than this?

I believe that is all that is required for AVR.

As far as I know avr-gcc does just one thing that goes beyond implementing interrupts as naked functions with canned prologue/epilogue: it applies a final peephole pass that avoids push/pop of any registers that an interrupt handler never touches. Probably not too hard to replicate this in an LLVM backend.

For my purposes an AVR backend for LLVM would need to be almost 100% source compatible with gcc. From what I understand about LLVM, this comes largely for free.

LLVM appears to properly support the GCC compiler barrier idiom:

   asm volatile ("":::"memory")

so that is good.

John

Anyone else interested in an AVR backend?

If so, for what members of the AVR family? If we do a port, likely it'll support only the ATmegas.

John

I have a client who might well make use of an AVR32 port, but I suspect
that machine is very different than the one you are currently examining.

shap

I have a client who might well make use of an AVR32 port, but I suspect
that machine is very different than the one you are currently examining.

I have not looked at AVR32 closely but my understanding is that it is a new architecture that shares a substring with AVR for marketing reasons.

John

GCC for AVR is awesome but, as far as I know, until very little time
ago, compiler support for PIC was close to none.

Sounds about right. But the translation architecture and the cache are
consistent at all reasonable page sizes, which puts it a big step ahead
of ARM for my purposes, and it's available as an electronic design for
embedding in CPLDs, which is sometimes convenient.

shap

GCC for AVR is awesome

For cross-compiling, it is awesome. For compiler research, not so much.

John

Jonathan S. Shapiro kirjoitti:

There is an email thread under llvm-commits titled:
[llvm-commits] PATCH for PIC16 target.
One of the replies to this thread explains some of the challenges that
we are facing on PIC16

Ali.

[llvm-commits] PATCH for PIC16 target.

Do you have a link? Google isn't turning this up.

I'd be interested in hearing more about this experience...

Thanks,

John

Do you have a link? Google isn't turning this up.

http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20080512/062319.html

Do you have a link? Google isn't turning this up.

http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20080512/062319.html

Wow, PIC looks like a brutal port.

AVR would be easy in comparison: stack-based architecture with plenty of registers. However, these architectures share:

- 8-bit loads, stores, and arithmetic ops.
- Harvard architecture

What sizes and alignments you choosing for the machine-dependent types? avr-gcc for example has:

sizeof(short)=2
sizeof(int)=2
sizeof(long)=4
sizeof(long long)=8
sizeof(int *)=2
sizeof(enum)=2
alignof(anything)=1

For any architecture where sizeof(int) > sizeof(register) it is desirable avoid whenever possible being forced to perform int-sized computations, which tend to be extremely inefficient, by C's promote to integer tendencies. I think this is what is being discussed in "challenge #1" in the mail to llvm-commits above. This optimization is crucial for MCU compilers.

John

Wow, PIC looks like a brutal port.

It is brutal...

sizeof(short)=2
sizeof(int)=2
sizeof(long)=4
sizeof(long long)=8
sizeof(int *)=2
sizeof(enum)=2
alignof(anything)=1

We have the same size and alignment exept for long long which is not
supported.

For any architecture where sizeof(int) > sizeof(register) it is

desirable

avoid whenever possible being forced to perform int-sized computations,

which tend to be extremely inefficient, by C's promote to integer
tendencies. I think this is what is being discussed in "challenge #1"

in

the mail to llvm-commits above. This optimization is crucial for MCU
compilers.

The problem of integer promotions manifest differently. "challenge #1"
refers to the problem and solution that we chose regarding legalizing
feature of LLVM where you can define for it the granularity of your
operations. For example in an 8-bit MCU, all arithmetic must be 8-bit.
So if you add two 32-bit values, you have add:i32 and the compiler must
lower them to four add:i8.

Cheers.
Ali