This version of the LLVM-CBE library works with LLVM r202033. You will have to compile this version of LLVM before you try to use LLVM-CBE. This guide will walk you through the compilation and installation of both tools and show usage statements to verify that the LLVM-CBE library is compiled correctly.
The library is known to compile on various linux versions (Redhat, Mageia, Ubuntu, Debian).
LLVM-CBE relies on specific LLVM internals, and so it is best to use it with a specific revision of the LLVM development tree. Currently, llvm-cbe works with LLVM 3.5.
To convert c to llvm ir you will need the clang compiler. To aid you, we have forked the repository at the appropriate revisions:
As llvm-cbe is a prototype library, we only use it with debugging enabled. sample of commands to do that is as follows:
cd $HOME
git clone https://github.com/llvm-mirror/llvm
cd llvm
git checkout release_35
cd tools
git clone https://github.com/llvm-mirror/clang
cd clang
git checkout release_35
cd $HOME/llvm
./configure --enable-debug-symbols --prefix=/usr/local --build=<your info>
make -j16
sudo make install
Note: The --build
option is important, it should match your gcc -v
output:
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-mageia-linux-gnu/4.8.2/lto-wrapper
Target: x86_64-mageia-linux-gnu
Configured with: ../configure --prefix=/usr --libexecdir=/usr/lib --with-slibdir=/lib
In this example, the --build
variable is:
./configure --enable-debug-symbols --prefix=/usr/local --build=x86_64-mageia-linux-gnu
Note: Building LLVM with the make -j16
command uses ~10GB of memory. On less robust machines it is recommended to just use make
instead.
Sample commands to download and compile llvm-cbe are:
git clone https://github.com/draperlaboratory/llvm-cbe.git llvm-cbe
cd llvm-cbe
./autoconf/AutoRegen.sh
./configure --with-llvmsrc=$HOME/llvm --with-llvmobj=$HOME/llvm
make -j16
The directory $HOME/llvm
is the directory you compiled LLVM in step 1. We assume you were in your home directory (/home/yourusername/
in Linux) when you compiled.
If llvm-cbe compiles, you should be able to run it with the following commands.
$ cd llvm-cbe/test/selectionsort
$ ls
main.c
$ clang -S -emit-llvm main.c
$ ls
main.c main.ll
$ llvm-cbe main.ll
$ cat main.cbe.c
/* Provide Declarations */
#include <stdarg.h>
#include <setjmp.h>
#include <limits.h>
/* get a declaration for alloca */
#if defined(__CYGWIN__) || defined(__MINGW32__)
#define alloca(x) __builtin_alloca((x))
#define _alloca(x) __builtin_alloca((x))
#elif defined(__APPLE__)
extern void *__builtin_alloca(unsigned long);
#define alloca(x) __builtin_alloca(x)
#define longjmp _longjmp
#define setjmp _setjmp
#elif defined(__sun__)
#if defined(__sparcv9)
extern void *__builtin_alloca(unsigned long);
#else
extern void *__builtin_alloca(unsigned int);
#endif
#define alloca(x) __builtin_alloca(x)
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__arm__)
#define alloca(x) __builtin_alloca(x)
#elif defined(_MSC_VER)
#define inline _inline
#define alloca(x) _alloca(x)
#else
#include <alloca.h>
#endif
#ifndef __GNUC__ /* Can only support "linkonce" vars with GCC */
#define __attribute__(X)
#endif
#if defined(__GNUC__) && defined(__APPLE_CC__)
#define __EXTERNAL_WEAK__ __attribute__((weak_import))
#elif defined(__GNUC__)
#define __EXTERNAL_WEAK__ __attribute__((weak))
#else
#define __EXTERNAL_WEAK__
#endif
#if defined(__GNUC__) && defined(__APPLE_CC__)
#define __ATTRIBUTE_WEAK__
#elif defined(__GNUC__)
#define __ATTRIBUTE_WEAK__ __attribute__((weak))
#else
#define __ATTRIBUTE_WEAK__
#endif
#if defined(__GNUC__)
#define __HIDDEN__ __attribute__((visibility("hidden")))
#endif
#ifdef __GNUC__
#define LLVM_NAN(NanStr) __builtin_nan(NanStr) /* Double */
#define LLVM_NANF(NanStr) __builtin_nanf(NanStr) /* Float */
#define LLVM_NANS(NanStr) __builtin_nans(NanStr) /* Double */
#define LLVM_NANSF(NanStr) __builtin_nansf(NanStr) /* Float */
#define LLVM_INF __builtin_inf() /* Double */
#define LLVM_INFF __builtin_inff() /* Float */
#define LLVM_PREFETCH(addr,rw,locality) __builtin_prefetch(addr,rw,locality)
#define __ATTRIBUTE_CTOR__ __attribute__((constructor))
#define __ATTRIBUTE_DTOR__ __attribute__((destructor))
#define LLVM_ASM __asm__
#else
#define LLVM_NAN(NanStr) ((double)0.0) /* Double */
#define LLVM_NANF(NanStr) 0.0F /* Float */
#define LLVM_NANS(NanStr) ((double)0.0) /* Double */
#define LLVM_NANSF(NanStr) 0.0F /* Float */
#define LLVM_INF ((double)0.0) /* Double */
#define LLVM_INFF 0.0F /* Float */
#define LLVM_PREFETCH(addr,rw,locality) /* PREFETCH */
#define __ATTRIBUTE_CTOR__
#define __ATTRIBUTE_DTOR__
#define LLVM_ASM(X)
#endif
#if __GNUC__ < 4 /* Old GCC's, or compilers not GCC */
#define __builtin_stack_save() 0 /* not implemented */
#define __builtin_stack_restore(X) /* noop */
#endif
#if __GNUC__ && __LP64__ /* 128-bit integer types */
typedef int __attribute__((mode(TI))) llvmInt128;
typedef unsigned __attribute__((mode(TI))) llvmUInt128;
#endif
#ifndef __cplusplus
typedef unsigned char bool;
#endif
/* Support for floating point constants */
typedef unsigned long long ConstantDoubleTy;
typedef unsigned int ConstantFloatTy;
typedef struct { unsigned long long f1; unsigned short f2; unsigned short pad[3]; } ConstantFP80Ty;
typedef struct { unsigned long long f1; unsigned long long f2; } ConstantFP128Ty;
/* Global Declarations */
/* External Global Variable Declarations */
typedef struct { unsigned char array[26]; } _OC_L_OC_str_t ;
typedef struct { unsigned char array[3]; } _OC_L_OC_str1_t ;
typedef struct { unsigned char array[19]; } _OC_L_OC_str2_t ;
typedef struct { unsigned char array[33]; } _OC_L_OC_str3_t ;
typedef struct { unsigned char array[4]; } _OC_L_OC_str4_t ;
/* Function Declarations */
double fmod(double, double);
float fmodf(float, float);
long double fmodl(long double, long double);
extern int main(void);
extern int printf(unsigned char *,...);
extern int __isoc99_scanf(unsigned char *,...);
/* Global Variable Declarations */
/* Global Variable Definitions and Initialization */
static _OC_L_OC_str_t _OC_L_OC_str = { "Enter number of elements\n" };
static _OC_L_OC_str1_t _OC_L_OC_str1 = { "%d" };
static _OC_L_OC_str2_t _OC_L_OC_str2 = { "Enter %d integers\n" };
static _OC_L_OC_str3_t _OC_L_OC_str3 = { "Sorted list in ascending order:\n" };
static _OC_L_OC_str4_t _OC_L_OC_str4 = { "%d\n" };
/* Function Bodies */
static inline int llvm_fcmp_ord(double X, double Y) { return X == X && Y == Y; }
static inline int llvm_fcmp_uno(double X, double Y) { return X != X || Y != Y; }
static inline int llvm_fcmp_ueq(double X, double Y) { return X == Y || llvm_fcmp_uno(X, Y); }
static inline int llvm_fcmp_une(double X, double Y) { return X != Y; }
static inline int llvm_fcmp_ult(double X, double Y) { return X < Y || llvm_fcmp_uno(X, Y); }
static inline int llvm_fcmp_ugt(double X, double Y) { return X > Y || llvm_fcmp_uno(X, Y); }
static inline int llvm_fcmp_ule(double X, double Y) { return X <= Y || llvm_fcmp_uno(X, Y); }
static inline int llvm_fcmp_uge(double X, double Y) { return X >= Y || llvm_fcmp_uno(X, Y); }
static inline int llvm_fcmp_oeq(double X, double Y) { return X == Y ; }
static inline int llvm_fcmp_one(double X, double Y) { return X != Y && llvm_fcmp_ord(X, Y); }
static inline int llvm_fcmp_olt(double X, double Y) { return X < Y ; }
static inline int llvm_fcmp_ogt(double X, double Y) { return X > Y ; }
static inline int llvm_fcmp_ole(double X, double Y) { return X <= Y ; }
static inline int llvm_fcmp_oge(double X, double Y) { return X >= Y ; }
int main(void) {
unsigned int retval; /* Address-exposed local */
struct { unsigned int array[100]; } array ; /* Address-exposed local */
unsigned int n; /* Address-exposed local */
unsigned int c; /* Address-exposed local */
unsigned int d; /* Address-exposed local */
unsigned int position; /* Address-exposed local */
unsigned int swap; /* Address-exposed local */
unsigned int reg2mem_20_alloca_20_point;
unsigned int call;
unsigned int call1;
unsigned int n_1;
unsigned int call2;
unsigned int c_2;
unsigned int n_3;
unsigned int c_4;
unsigned int call3;
unsigned int c_5;
unsigned int c_6;
unsigned int n_7;
unsigned int c_8;
unsigned int c_9;
unsigned int d_10;
unsigned int n_11;
unsigned int position_12;
unsigned int arrayidx11_13;
unsigned int d_14;
unsigned int arrayidx13_15;
unsigned int d_16;
unsigned int d_17;
unsigned int position_18;
unsigned int c_19;
unsigned int c_20;
unsigned int arrayidx21_21;
unsigned int position_22;
unsigned int arrayidx23_23;
unsigned int c_24;
unsigned int swap_25;
unsigned int position_26;
unsigned int c_27;
unsigned int call32;
unsigned int c_28;
unsigned int n_29;
unsigned int c_30;
unsigned int arrayidx37_31;
unsigned int call38;
unsigned int c_32;
reg2mem_20_alloca_20_point = ((int )0u);
retval = 0u;
call = printf(((&_OC_L_OC_str.array[0u])));
call1 = __isoc99_scanf(((&_OC_L_OC_str1.array[0u])), (&n));
n_1 = n;
call2 = printf(((&_OC_L_OC_str2.array[0u])), n_1);
c = 0u;
/* BasicBlock Size: 4*/
for(c_2 = c, n_3 = n; (((int )c_2) < ((int )n_3)); c_2 = c ) {
n_3 = n;
c_4 = c;
call3 = __isoc99_scanf(((&_OC_L_OC_str1.array[0u])), ((&array.array[(((long long )(int )c_4))])));
c_5 = c;
c = (c_5 + 1u);
} /* end of printLoop */
c = 0u;
/* BasicBlock Size: 5*/
for(c_6 = c, n_7 = n; (((int )c_6) < ((int )(n_7 - 1u))); c_6 = c ) {
n_7 = n;
c_8 = c;
position = c_8;
c_9 = c;
d = (c_9 + 1u);
/* BasicBlock Size: 4*/
for(d_10 = d, n_11 = n; (((int )d_10) < ((int )n_11)); d_10 = d ) {
n_11 = n;
position_12 = position;
arrayidx11_13 = *((&array.array[(((long long )(int )position_12))]));
d_14 = d;
arrayidx13_15 = *((&array.array[(((long long )(int )d_14))]));
if ( (((int )arrayidx11_13) > ((int )arrayidx13_15)) ) {
d_16 = d;
position = d_16;
}
else {
}
d_17 = d;
d = (d_17 + 1u);
} /* end of printLoop */
position_18 = position;
c_19 = c;
if ( (position_18 != c_19) ) {
c_20 = c;
arrayidx21_21 = *((&array.array[(((long long )(int )c_20))]));
swap = arrayidx21_21;
position_22 = position;
arrayidx23_23 = *((&array.array[(((long long )(int )position_22))]));
c_24 = c;
*((&array.array[(((long long )(int )c_24))])) = arrayidx23_23;
swap_25 = swap;
position_26 = position;
*((&array.array[(((long long )(int )position_26))])) = swap_25;
}
else {
}
c_27 = c;
c = (c_27 + 1u);
position_12 = position;
arrayidx11_13 = *((&array.array[(((long long )(int )position_12))]));
d_14 = d;
arrayidx13_15 = *((&array.array[(((long long )(int )d_14))]));
if ( (((int )arrayidx11_13) > ((int )arrayidx13_15)) ) {
}
else {
}
} /* end of printLoop */
call32 = printf(((&_OC_L_OC_str3.array[0u])));
c = 0u;
/* BasicBlock Size: 4*/
for(c_28 = c, n_29 = n; (((int )c_28) < ((int )n_29)); c_28 = c ) {
n_29 = n;
c_30 = c;
arrayidx37_31 = *((&array.array[(((long long )(int )c_30))]));
call38 = printf(((&_OC_L_OC_str4.array[0u])), arrayidx37_31);
c_32 = c;
c = (c_32 + 1u);
} /* end of printLoop */
return 0u;
}
$ gcc -o main.cbe main.cbe.c
$ ls
main.c main.cbe main.cbe.c main.ll
$ ./main.cbe