# DragonEgg - Using LLVM as a GCC backend

DragonEgg is a gcc plugin that replaces GCC's optimizers and code generators with those from the LLVM project. It works with gcc-4.5 or newer, can target the x86-32/x86-64 and ARM processor families, and has been successfully used on the Darwin, FreeBSD, KFreeBSD, Linux and OpenBSD platforms. It fully supports Ada, C, C++ and Fortran. It has partial support for Go, Java, Obj-C and Obj-C++.

## Goals

- Fully support all GCC languages

## Current Status

- Works best with gcc-4.6.
- Fortran works very well. Ada, C and C++ also work well. Ada works poorly with gcc-4.7 and later.
- It can compile a reasonable amount of Obj-C, Obj-C++ and Go.
- It can compile simple Java programs, but they don't execute properly (this is a consequence of the java front-end not supporting GCC's LTO).
- Debug info is poor.

## Releases

- DragonEgg-3.3 is the most recent DragonEgg release. It requires LLVM-3.3 and gcc 4.5 or newer.

  The 3.3 release has the following notable changes:

  - Supports gcc-4.8 (requires gcc-4.8.1 or newer).
  - Object files can be written directly using LLVM’s integrated assembler.
  - Produces saner debug info.
  - Bitfields can now contain arbitrary scalar types (useful for Ada).

- DragonEgg-3.2 was the sixth DragonEgg release. It requires LLVM-3.2 and gcc-4.5, gcc-4.6 or gcc-4.7 (gcc-4.7 is only partially supported).

  The 3.2 release has the following notable changes:

  - Able to load LLVM plugins such as Polly.
  - Supports thread-local storage models.
  - Passes knowledge of variable lifetimes to the LLVM optimizers.
  - No longer requires GCC to be built with LTO support.

- DragonEgg-3.1 was the fifth DragonEgg release. It requires LLVM-3.1 and gcc-4.5, gcc-4.6 or gcc-4.7 (gcc-4.7 is only partially supported).

  The 3.1 release has the following notable changes:

  - Partial support for gcc-4.7. Ada support is poor, but other languages work fairly well.
  - Support for ARM processors. Some essential gcc headers that are needed to build DragonEgg for ARM are not installed by gcc. To work around this, copy the missing headers from the gcc source tree.
  - Better optimization for Fortran by exploiting the fact that Fortran scalar arguments have 'restrict' semantics.
  - Better optimization for all languages by passing information about type aliasing and type ranges to the LLVM optimizers.
  - A regression test-suite was added.

- DragonEgg-3.0 was the fourth DragonEgg release. It requires LLVM-3.0 and gcc-4.5 or gcc-4.6.

  The 3.0 release has the following notable changes:

  - GCC version 4.6 is now fully supported.
  - Patching and building GCC is no longer required: the plugin should work with your system GCC (version 4.5 or 4.6; on Debian/Ubuntu systems the gcc-4.5-plugin-dev or gcc-4.6-plugin-dev package is also needed).
  - The `-fplugin-arg-dragonegg-enable-gcc-optzns` option, which runs GCC's optimizers as well as LLVM's, now works much better. This is the option to use if you want ultimate performance! It is still experimental though: it may cause the plugin to crash. Setting the optimization level to `-O4` when using this option will optimize even harder, though this usually doesn't result in any improvement over `-O3`.
  - The type and constant conversion logic has been almost entirely rewritten, fixing a multitude of obscure bugs.

  Known problems with the DragonEgg-3.0 release:

  - The Makefile tries to use `svnversion` to get the LLVM revision. To fix this, replace this line

              REVISION:=$(shell svnversion -n $(TOP_DIR))

    with

              REVISION:=3.0

- DragonEgg-2.9 was the third DragonEgg release. It requires LLVM-2.9 and gcc-4.5.

  The 2.9 release has the following notable changes:

  - The plugin is much more stable when compiling Fortran.
  - Inline assembly where an asm output is tied to an input of a different size is now supported in many more cases.
  - Basic support for the __float128 type was added. It is now possible to generate LLVM IR from programs using __float128 but code generation does not work yet.
  - Compiling Java programs no longer systematically crashes the plugin.

  Common problems with building the DragonEgg-2.9 release:

  - If you had to install the GMP, MPC or MPFR libraries locally in order to build gcc-4.5, then the dragonegg build may fail due to not finding header files from the libraries. You can tell the dragonegg build system where to find them by setting CPPFLAGS before calling make:

                CPPFLAGS="-I/path/to/header/files -I/another/header/path/" make

  - The build fails if you are using a case insensitive file system, such as the default darwin filesystem `HFS+`. To fix this, apply this patch.

- DragonEgg-2.8 was the second DragonEgg release. It requires LLVM-2.8 and gcc-4.5.

  The 2.8 release had the following notable changes:

  - The plugin loads faster due to exporting fewer symbols.
  - Additional vector operations such as addps256 are now supported.
  - Ada global variables with no initial value are no longer zero initialized, resulting in better optimization.
  - The '-fplugin-arg-dragonegg-enable-gcc-optzns' flag now runs all gcc optimizers, rather than just a handful.
  - Fortran programs using common variables now link correctly.
  - GNU OMP constructs no longer crash the compiler.

  Known problems with the DragonEgg-2.8 release:

  - Functions returning complex numbers are not handled in an ABI conformant way. This means for example that if code compiled with dragonegg calls a function in a system library that returns a complex number then you get a bogus result. The fix in subversion commit 117649 can be applied to the dragonegg-2.8 source to resolve the problem.
  - Calling `floor` then converting the result to a long integer type can result in link failures due to an undefined reference to `__builtin_lfloor`. Likewise for `ceil` and variants like `floorf`. The fix in subversion commit 118499 can be applied to the dragonegg-2.8 source to resolve the problem.
  - Some OpenMP programs fail to work when compiled without optimization. This has been fixed in the development version of LLVM. Compile at `-O1` or better to workaround this.
  - Programs that throw an uncaught exception when there are destructors to be run when unwinding would crash rather than terminating cleanly. The fix in subversion commit 120096 can be applied to the dragonegg-2.8 source to resolve the problem.

- DragonEgg-2.7 was the first ever DragonEgg release. It works with LLVM-2.7 and gcc-4.5.

  Known problems with the DragonEgg-2.7 release:

  - If `gcc-4.5` was configured with a target triple of the form `x86_64-linux-gnu` or `i386-linux-gnu` then the build fails with `"error: llvm-os.h: No such file or directory"`. Use the four component style `x86_64-unknown-linux-gnu` or `i386-unknown-linux-gnu` instead.
  - Fortran common variables may not be output when they should be, causing link failures.
  - Programs using OpenMP directives crash the plugin.

  These problems have been fixed in the 2.8 release of DragonEgg.

## DragonEgg in action

Here is the result of compiling a simple "hello world" program with gcc-4.5:

    $ gcc hello.c -S -O1 -o -
    	.file	"hello.c"
    	.section	.rodata.str1.1,"aMS",@progbits,1
    .LC0:
    	.string	"Hello world!"
    	.text
    .globl main
    	.type	main, @function
    main:
    	subq	$8, %rsp
    	movl	$.LC0, %edi
    	call	puts
    	movl	$0, %eax
    	addq	$8, %rsp
    	ret
    	.size	main, .-main
    	.ident	"GCC: (GNU) 4.5.0 20090928 (experimental)"
    	.section	.note.GNU-stack,"",@progbits

Adding `-fplugin=path/dragonegg.so` to the gcc command line causes the program to be optimized and codegened by LLVM instead:

    $ gcc hello.c -S -O1 -o - -fplugin=./dragonegg.so
    	.file	"hello.c"
    # Start of file scope inline assembly
    	.ident	"GCC: (GNU) 4.5.0 20090928 (experimental) LLVM: 82450:82981"
    # End of file scope inline assembly

    	.text
    	.align	16
    	.globl	main
    	.type	main,@function
    main:
    	subq	$8, %rsp
    	movl	$.L.str, %edi
    	call	puts
    	xorl	%eax, %eax
    	addq	$8, %rsp
    	ret
    	.size	main, .-main
    	.type	.L.str,@object
    	.section	.rodata.str1.1,"aMS",@progbits,1
    .L.str:
    	.asciz	"Hello world!"
    	.size	.L.str, 13

    	.section	.note.GNU-stack,"",@progbits

Adding `-fplugin-arg-dragonegg-emit-ir` or `-flto` causes LLVM IR to be output (you need to request assembler output, -S, rather than object code output, -c, since otherwise gcc will pass the LLVM IR to the system assembler, which will doubtless fail to assemble it):

    $ gcc hello.c -S -O1 -o - -fplugin=./dragonegg.so -fplugin-arg-dragonegg-emit-ir
    ; ModuleID = 'hello.c'
    target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
    target triple = "x86_64-unknown-linux-gnu"

    module asm "\09.ident\09\22GCC: (GNU) 4.5.0 20090928 (experimental) LLVM: 82450:82981\22"

    @.str = private constant [13 x i8] c"Hello world!\00", align 1 ; <[13 x i8]*> [#uses=1]

    define i32 @main() nounwind {
    entry:
      %0 = tail call i32 @puts(i8* getelementptr inbounds ([13 x i8]* @.str, i64 0, i64 0)) nounwind ; <i32> [#uses=0]
      ret i32 0
    }

    declare i32 @puts(i8* nocapture) nounwind

## Getting it

Get the DragonEgg-3.3 source code:

    	wget http://llvm.org/releases/3.3/dragonegg-3.3.src.tar.gz

Unpack it:

    	tar xzf dragonegg-3.3.src.tar.gz

Install version 3.3 of LLVM, for example by downloading and installing the LLVM-3.3 binaries (mysteriously referred to as clang binaries) for your platform.

Make sure you have gcc-4.5, gcc-4.6, gcc-4.7 or gcc-4.8 installed (you do not need to build your own copy); gcc-4.6 works best. On Debian and Ubuntu you need to install the corresponding plugin-dev package (gcc-4.5-plugin-dev, gcc-4.6-plugin-dev, etc).

Doing

    	GCC=gcc-4.6 make

(if using gcc-4.6; otherwise replace gcc-4.6 with your gcc version) in the `dragonegg-3.3.src` directory should then build `dragonegg.so`. If the LLVM binaries are not in your path then you can use

    	GCC=gcc-4.6 LLVM_CONFIG=directory_where_llvm_installed/bin/llvm-config make

If you only built LLVM and did not install it then you can still build dragonegg by setting LLVM_CONFIG to point to the copy of llvm-config in the build tree.

To use `dragonegg.so`, compile something with gcc-4.6, or whatever version of gcc you used, adding `-fplugin=path_to_dragonegg/dragonegg.so` to the command line. See the `README` file for more details and useful command line options.

## Getting the development version

Get the source code for the development version of DragonEgg:

    	svn co http://llvm.org/svn/llvm-project/dragonegg/trunk dragonegg

Get the source code for the development version of LLVM:

    	svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm

Build LLVM in the usual way.

Install gcc-4.5, gcc-4.6, gcc-4.7 or gcc-4.8 (you do not need to build your own copy). On Debian and Ubuntu you need to install the corresponding plugin-dev package (gcc-4.5-plugin-dev, gcc-4.6-plugin-dev, etc).

Doing

    	GCC=place_you_installed_gcc/bin/gcc make

in the `dragonegg` directory should then build `dragonegg.so`. See the `README` file for more details.

To use `dragonegg.so`, compile something with your just-installed version of `gcc`, adding `-fplugin=path_to_dragonegg/dragonegg.so` to the command line. See the `README` file for more details and useful command line options.

## It doesn't work!

Sorry about that! Please report bugs and problems to the LLVM developers' mailing list, or using LLVM's bugzilla.

Suggestions for improvement are welcome. Patches are even more welcome!

## More information

There was a talk "Reimplementing llvm-gcc as a gcc plugin" about DragonEgg at the 2009 llvm developers meeting. At that time, DragonEgg was known as "the gcc plugin".

[Slides]

[Video] (Computer)

[Video] (Mobile)