ACCGen Quickstart

Introduction

In this document, I will describe how to generate a new LLVM compiler backend for the ARM architecture using only the ArchC ARM model and the ACCGen (ArchC Compiler Generator) tool. You can also modify the model in order to generate a slightly different backend, or try to generate the backend for a different architecture.

Updated 9/6/2013: Now ACCGen is included into the ArchC virtual machine (Ubuntu virtual machine with ArchC 2.2). If you decide to download and use it, you can assume all configuration and installing steps of this tutorial are already completed.

Environment

The ACCGen project started in 2009 and therefore it is still linked to the LLVM version 2.5, a version that is already a bit old. There should not be much difficulty in porting to newer LLVM versions and contributions are greatly appreciated. Below you may find listed the software environment used to test the tool.

1) LLVM version: 2.5

2) llvm-gcc (compiler frontend) version: 4.2-2.5 precompiled for linux or 4.2-2.5 source code. You may also check additional versions here

3) gcc version used to compile LLVM: 4.3

4) ArchC: 2.1

5) SystemC 2.2.0

6) ACCGen: release-1

-- or access via svn:

$ svn co http://lampiao.lsc.ic.unicamp.br/svn/acllvmbackend/tags/release-1

7) ARMv5 model: 0.7.0

Building SystemC

You may start my getting all stuff above and organizing them in your favourite folder. Uncompress the files. Start by installing SystemC and ArchC. Please note that in this quick tutorial I will make a minimum ArchC install without simulator or binutils generation support. If you already have ArchC installed, adjust to use your installation paths. If you want to perform a more complete installation, refer to our installation guides. I will start with SystemC because it is a prerequisite for ArchC, although we will not use SystemC features in this tutorial:

$ wget http://www.pfb.no/files/systemc-2.2.0-ubuntu10.10.patch
$ tar -xvf systemc-2.2.0.tgz
$ cd systemc-2.2.0
$ patch -p1 < ../systemc-2.2.0-ubuntu10.10.patch
$ ./configure
$ make
$ cd ../

Building ArchC

Now compile a minimal ArchC configuration with SystemC. If we do not built it with SystemC, we will not have the acpp (preprocessor) lib required to ACCGen. If you are using ArchC 2.1 (not newer versions), you need to apply a small patch to add some functionality required by ACCGen:

$ wget http://www.ic.unicamp.br/~auler/fix-archc-2.1.patch
$ cd archc-2.1
$ patch -p1 < ../fix-archc-2.1.patch
$ ./configure --prefix=$(pwd)/../install --with-systemc=$(pwd)/../systemc-2.2.0
$ make && make install

Building ACCGen

Now compile ACCGen. You will need libboost. I used g++ 4.4.3. Begin by opening the Makefile document and adapting to your paths:

$ nano Makefile

Change ARCH_SRC_DIR to point to your ArchC source dir and ARCH_INC to point to your ArchC installation folder's include dir. The first lines should look like:

ARCHC_SRC_DIR := ../archc-2.1/src
ARCHC_INC := -I../install/include/archc/

Then build the project:

$ make

Generating an ARM Backend

Now you can run ACCGen by executing the genllvmbe executable file:

$ ./genllvmbe

Before generating the backend, we need to setup some environmental variables:

$ cd ..
$ export LLVMDIR=$(pwd)/llvm-2.5
$ export RULESFILE=$(pwd)/accgen/Parser/rules.txt
$ export TEMPLATEDIR=$(pwd)/accgen/template

Now it is time to generate the ARM backend using ACCGen. If you are using the ARM model v0.7.0, you do not have yet the compiler related addition information which is required by ACCGen to understand the instructions of this model. Download and apply the following patch to add this information.

$ wget http://www.ic.unicamp.br/~auler/fix-arm-v0.7.0.patch
$ cd armv5-v0.7.0
$ patch -p1 < ../fix-arm-v0.7.0.patch
$ ../accgen/genllvmbe armv5e.ac

You should wait around 4 minutes to complete the backend inference. When it finishes, it is time to build the LLVM using the new backend. ACCGen should already completed patching your LLVM source tree.

Building the LLVM source with the generated backend

Now you should apply a small patch to the llvm-2.5 code.

$ cd ..
$ wget http://www.ic.unicamp.br/~auler/llvm-2.5-fix.patch
$ cd llvm-2.5
$ patch -p1 < ../llvm-2.5-fix.patch
$ cd ..
$ mkdir llvm-obj
$ cd llvm-obj

Now, if you are using gcc 4.4.3 or newer like me, you should explictly switch versions because LLVM 2.5 code won't compile without gcc 4.3.

$ CC=gcc-4.3 CXX=g++-4.3 ../llvm-2.5/configure --prefix=$(pwd)/../install -enable-targets=armv5e
$ make && make install

It should take another 4 minutes.

Building or installing llvm-gcc

You need to prepare to install llvm-gcc, the frontend that compiles C/C++ code to LLVM intermediate language.

llvm-gcc has several target specific configuration options, you should read the README.LLVM file in its source tree, but here is a default build for Linux. Of course you can also download the binaries packages offered by the LLVM website (highly recommended), in this case you do not need to compile.

$ cd ..
$ mkdir gcc-obj
$ cd gcc-obj
$ CC=gcc-4.3 ../llvm-gcc4.2-2.5.source/configure --prefix=$(pwd)/../install --program-prefix=llvm- \ --enable-llvm=$(pwd)/../llvm-obj  --enable-languages=c,c++
$ make 
$ make install

If you downloaded a precompiled package, skip the steps above and prepare to set the path (I suppose you already uncompressed the package):

$ export PATH=$PATH:$(pwd)/llvm-gcc4.2-2.5-x86-linux-RHEL4/bin

Compiling a simple C program with the automatically generated backend

Now it is time to test the code generator. Type a simple C program and compile to test it. It should look like:

#include <stdio.h>

int
main() {
  int i = 0;
  scanf ("%d", &i);
  printf ("%d\n", i + 5);
  return 0;
}

Save as "test.c":

$ cd ..
$ vim test.c  # type program

Set paths to the backend:

$ export PATH=$PATH:$(pwd)/install/bin

And compile:

$ llvm-gcc -emit-llvm -c test.c -o test.bc
$ llc -march=Armv5e test.bc -o test.s

Now you can check the assembly language file test.s! If you changed the instruction descriptions or added instructions, you can see the effect on the generated assembly language file.

This ends our quickstart guide. If you want to assemble and link to generate a final executable, you can use ARM assemblers and linkers. The LLVM 2.5 only provides the compiler part.

Please notice that by generating the assembler and linker using ArchC, you may not be able to link with the GNU C Library. In these cases, you would be able to compile only bare-metal code which does not rely on a C Library (similar to Linux kernel C code).

In the case of the ARM backend, since it respects ARM ABI and conventions, you may still use regular ARM assemblers and linkers and produce user mode C applications. In the next blog entry, I will cover how to compile binutils ARM toolchains that work with the ARM ArchC simulator.