Targeting low level embedded

I'm new to LLVM and I'm trying to set it up to target a low level
embedded device with no OS. Therefore the final program needs to
perform variable initialization and be located at a certain address
location. Here is my basic flow:

Compile C to bytecode:
$ llvm-gcc -emit-llvm -c src1.c src2.c src3.c

Consolidate to one bytecode file:
$ llvm-link -o all.o src1.c src2.o src3.o

Emit assembly code:
$ llc -march=ppc32 -o all.s all.o

Assemble to machine code:
$ powerpc-eabi-as -o all.elf all.s

Relocate sections to target specific addresses:
$ powerpc-eabi-ld -T sections.ld -o relocated.elf all.elf

... then convert to an s-record and flash the device.

A few questions...

1. Is this the right approach?
2. Does llvm-gcc insert initialization code? It doesn't look like it,
but I may be missing something.
3. What is the difference between llvm-link and llvm-ld? Does
llvm-link do inter module optimization?
4. Can llvm-link or llvm-ld perform any memory placement, or does this
fall on binutils ld?

Thanks for any help!

-Tom

I'm new to LLVM and I'm trying to set it up to target a low level
embedded device with no OS. Therefore the final program needs to
perform variable initialization and be located at a certain address
location. Here is my basic flow:

Compile C to bytecode:
$ llvm-gcc -emit-llvm -c src1.c src2.c src3.c

Consolidate to one bytecode file:
$ llvm-link -o all.o src1.c src2.o src3.o

Emit assembly code:
$ llc -march=ppc32 -o all.s all.o

Assemble to machine code:
$ powerpc-eabi-as -o all.elf all.s

Relocate sections to target specific addresses:
$ powerpc-eabi-ld -T sections.ld -o relocated.elf all.elf

... then convert to an s-record and flash the device.

A few questions...

1. Is this the right approach?

You're trying to shoehorn LLVM into an environment it isn't really set
up for; if you've compiled llvm-gcc as a cross-compiler targeting
ppc32, then it should work roughly as well as it would work with gcc.
If llvm-gcc is an x86 compiler, you're likely to run into issues; see
http://llvm.org/docs/FAQ.html#platformindependent .

2. Does llvm-gcc insert initialization code? It doesn't look like it,
but I may be missing something.

Initialization for what, exactly? Is your toolchain not capable of
setting up writable data sections correctly?

3. What is the difference between llvm-link and llvm-ld? Does
llvm-link do inter module optimization?

If you want to break down the process into steps as small as possible,
just use llvm-link. llvm-ld is a combination of llvm-link and opt
-std-link-opts and optionally llc+as+ld.

4. Can llvm-link or llvm-ld perform any memory placement, or does this
fall on binutils ld?

What do you expect llc to output? llvm-link is not a linker in the
same way that ld is.

-Eli

2. Does llvm-gcc insert initialization code? It doesn't look like it,
but I may be missing something.

Initialization for what, exactly? Is your toolchain not capable of
setting up writable data sections correctly?

I think Tom was referring to the initialization code that copy data sections
and initialized zero-init variables from rom to ram. Generally this code is
found as an object file which you can link with your code object file. This
is not generated code but on the contrary handwritten assembly code.

- Christophe

Hi,

Tom Hawkins kirjoitti:

I'm new to LLVM and I'm trying to set it up to target a low level
embedded device with no OS. Therefore the final program needs to

> perform variable initialization and be located at a certain address
> location. Here is my basic flow:

We also have an embedded osless target (see http://tce.cs.tut.fi) using
LLVM very successfully. However, our target is not "pure and clean" LLVM
backend as we generate backends on the fly to allow easy and fast target
customization.

LLVM code generation framework is used in our toolchain for instruction
selection and register allocation but we do our own instruction
scheduling and "bundling" + the final assembly phase that generates the
bit images to be uploaded to the instruction memory and data memory.
Also the data memory layout is generated in our own code, that's where
the start address of data memory is fixed.

2. Does llvm-gcc insert initialization code? It doesn't look like it,
but I may be missing something.

How those images are to be uploaded/loaded/initialized in the final
device is not the problem of the compiler but a runtime loader of some
kind, thus target platform (and memory system) dependent.

You can generate an initializer code for the data memory which
in effect is then a simple "program loader" that copies the initial
values from a non-volatile memory (or some other source, from where
ever you want to initialize the program) to the RAM before starting the
actual main program. This can be a simple (assembly written) loop
in crt0 before calling main, for example. In a multiprocess operating
system env this would be the responsibility of the process
initialization routines (the exec() syscall?).

Or you can have the data memory initialized by a host processor before
it starts your slave processor. As you see, it all depends on your
embedded platform, thus it's clearly not the compiler's responsibility.