Monthly Archives: October 2013

Using ELLCC to Build Itself, Including Canadian Cross Builds

The ELLCC tool chain can now completely build itself. Currently the build has been tested only on Linux systems. The steps I’ll use here are:

  1. Build ELLCC using the system compiler (bootstrap build)
  2. Build it again with itself (sanity build)
  3. Cross build it for another target machine (show off build)

ELLCC supports several target processors:

  • arm – little endian ARM
  • armeb – big endian ARM
  • i366 – x86 in 32 bit mode
  • microblaze – the Xilinx soft-core processor for FPGAs
  • mips – big endian Mips
  • mipsel – little endian Mips
  • ppc – the Power PC in 32 bit mode
  • x86_64 – x86 in 64 bit mode

The compiler we’ll be building can target all of them.

Go into a directory and get the latest ELLCC top of tree (TOT):

[~] dev% svn checkout ellcc

I checkout into a directory called ellcc, but the name isn’t important.
In this example. I checked out the files in my home directory. Now we can do the initial bootstrap build:

[~] dev% cd ellcc
[~/ellcc] dev% ./build

The build takes quite a while because it is building ecc, the clang/LLVM based C/C++ compiler, GNU binutils for the assemblers, linker, and utilities, GDB for debugging, and QEMU for all the target processors for testing purposes. It also builds a compete set of run-time libraries:

  • libc++ for the C++ standard library
  • libc++ABI for C++ run-time suport
  • libunwind for C++ exception handling
  • musl for the C standard library
  • compiler-rt for low-level support routines
  • ncurses for terminal support
  • zlib for compression/decompression

All of these libraries are built for all the supported target processors.

When the bootstrap build is finished, you’ll get a message like this:

Please run the build script again to bootstrap ecc.
This may be done a few times:
1. ecc is built with itself (compiled with gcc) and libecc.
2. ecc is built with itself (compiled with itself) and libecc.

Run build again. This will build the ELLCC tools with themselves to complete the bootstrap.

Just run the same build command again:

[~/ellcc] dev% ./build

This time you won’t get the message above, since ELLCC has been completely bootstrapped.

Now for the fun part, a Canadian cross build.
In this step, we’ll use our newly built compiler to build a compiler that will run on a different target system. In this case, the ELLCC build rules don’t bother with compiling QEMU, since it is only used for ELLCC development. In addition, we can skip building the libraries, since they have already been built. I’ll do a build for an ARM target:

[~/ellcc] dev%de>[~/ellcc] dev% ./build arm

When this build completes, we’ll have a new directory populated with the ARM executables, bin-arm-linux:

[~/ellcc] dev% ls bin-arm-linux/
arm-elf-as*     ecc-gdb*      i386-elf-as*       llvm-extract*     macho-dump*
bugpoint*       ecc-gprof*    llc*               llvm-link*        microblaze-elf-as*
clang-check*    ecc-ld*       lli*               llvm-mc*          mips-elf-as*
clang-format*   ecc-ld.bfd*   lli-child-target*  llvm-mcmarkup*    not*
clang-tblgen*   ecc-nm*       llvm-ar*           llvm-nm*          opt*
ecc*            ecc-objcopy*  llvm-as*           llvm-objdump*     ppc64-elf-as*
ecc++@          ecc-objdump*  llvm-bcanalyzer*   llvm-ranlib@      ppc-elf-as*
ecc-addr2line*  ecc-ranlib*   llvm-config*       llvm-readobj*     sparc-elf-as*
ecc-ar*         ecc-readelf*  llvm-config-host*  llvm-rtdyld*      x86_64-elf-as*
ecc-as*         ecc-size*     llvm-cov*          llvm-size*
ecc-c++filt*    ecc-strings*  llvm-diff*         llvm-stress*
ecc-elfedit*    ecc-strip*    llvm-dis*          llvm-symbolizer*
ecc-embedspu*   FileCheck*    llvm-dwarfdump*    llvm-tblgen*

[~/ellcc] dev% ~/ellcc[~/ellcc] dev% file bin-arm-linux/ecc
bin-arm-linux/ecc: ELF 32-bit LSB executable, ARM, version 1, statically linked, BuildID[sha1]=0x9ff616a316ab010b46062f7fc1dff554ee7a6db8, not stripped
/bin/qemu-arm bin-arm-linux/ecc -v
clang version 3.4 (trunk)
Target: arm-unknown-linux-gnu
Thread model: posix
Selected GCC installation: 
[~/ellcc] dev

Very cool!

A Major ELLCC Milestone: Building a Completely non-gnu C++ Program for Linux

ELLCC (pronounced “elk”), the embedded compiler collection based on clang/LLVM, has reached a major milestone: The ability to create C++ programs for several target processors using a set of libraries based on libraries with non-gnu licences.

ELLCC incorporates a C/C++ compiler based on clang/LLVM (ecc). The current supported target processors are ARM (both little and big endian), i386, Microblaze (the Xilinx softcore processor), Mips (both big and little endian), PowerPC (32 bit only for now), and x86_64.

The first test case, using the LLVM lit test framework, looks pretty simple:

// Compile and run for every target.
// RUN: %armexx -o %t %s && %armrun %t  | FileCheck -check-prefix=CHECK %s
// RUN: %armebexx -o %t %s && %armebrun %t | FileCheck -check-prefix=CHECK %s
// RUN: %i386exx -o %t %s && %i386run %t | FileCheck -check-prefix=CHECK %s
// RUN: %microblazeexx -o %t %s && %microblazerun %t | FileCheck -check-prefix=CHECK %s
// RUN: %mipsexx -o %t %s && %mipsrun %t | FileCheck -check-prefix=CHECK %s
// RUN: %mipselexx -o %t %s && %mipselrun %t | FileCheck -check-prefix=CHECK %s
// RUN: %ppcexx -o %t %s && %ppcrun %t | FileCheck -check-prefix=CHECK %s
// FAIL: %ppc64exx -o %t %s && %ppc64run %t | FileCheck -check-prefix=CHECK %s
// RUN: %x86_64exx -o %t %s && %x86_64run %t | FileCheck -check-prefix=CHECK %s
// CHECK: foo.i = 10
// CHECK: bye
#include <cstdio>

class Foo {
    int i;
    Foo(int i) : i(i) { }
    int get() { return i; }
    ~Foo() { printf("bye\n"); }

int main(int argc, char** argv)
    Foo foo(10);
    printf("foo.i = %d\n", foo.get());

It does look pretty simple, but it represents:

  • ecc compiled from clang/LLVM (near) current
  • libc++ from the LLVM project built using ecc
  • libc++ABI from the LLVM project built using ecc
  • libunwind for handling non-static destructors and exceptions built using ecc
  • musl for the standard C library built using ecc
  • compiler-rt for low level processor support built using ecc

I have some more cleanup to do, but after that the next step will be a self hosted ELLCC.