From 7d822e7e330be8ab120fe2c7230a83e327f3d102 Mon Sep 17 00:00:00 2001 From: Benjamin Segovia Date: Tue, 21 Feb 2012 20:46:19 +0000 Subject: [PATCH] Started llvm work --- backend/CMakeLists.txt | 5 + backend/kernels/k | Bin 0 -> 368 bytes backend/kernels/k.ll | 10 + backend/kernels/k.s | 11 + backend/kernels/stdlib.h | 204 ++ backend/kernels/struct.cl | 10 + backend/kernels/struct.cl.o | Bin 0 -> 592 bytes backend/kernels/struct.cl.o.ll | 12 + backend/kernels/void.cl | 2 + backend/kernels/void.cl.o | Bin 0 -> 560 bytes backend/kernels/void.cl.o.cbe.c | 157 + backend/kernels/void.cl.o.ll | 12 + backend/src/CMakeLists.txt | 7 + backend/src/llc/.CMakeLists.txt.swp | Bin 0 -> 12288 bytes backend/src/llc/CMakeLists.txt | 9 + backend/src/llc/llc.cpp | 403 +++ backend/src/llvm/.GenBackend.cpp.swp | Bin 0 -> 147456 bytes backend/src/llvm/CMakeLists.txt | 20 + backend/src/llvm/GenBackend.cpp | 3638 ++++++++++++++++++++ backend/src/llvm/GenTargetMachine.h | 61 + backend/src/llvm/Makefile | 16 + .../llvm/TargetInfo/.GenBackendTargetInfo.cpp.swp | Bin 0 -> 12288 bytes backend/src/llvm/TargetInfo/CMakeLists.txt | 10 + .../src/llvm/TargetInfo/GenBackendTargetInfo.cpp | 41 + backend/src/llvm/TargetInfo/Makefile | 15 + 25 files changed, 4643 insertions(+) create mode 100644 backend/kernels/k create mode 100644 backend/kernels/k.ll create mode 100644 backend/kernels/k.s create mode 100644 backend/kernels/stdlib.h create mode 100644 backend/kernels/struct.cl create mode 100644 backend/kernels/struct.cl.o create mode 100644 backend/kernels/struct.cl.o.ll create mode 100644 backend/kernels/void.cl create mode 100644 backend/kernels/void.cl.o create mode 100644 backend/kernels/void.cl.o.cbe.c create mode 100644 backend/kernels/void.cl.o.ll create mode 100644 backend/src/llc/.CMakeLists.txt.swp create mode 100644 backend/src/llc/CMakeLists.txt create mode 100644 backend/src/llc/llc.cpp create mode 100644 backend/src/llvm/.GenBackend.cpp.swp create mode 100644 backend/src/llvm/CMakeLists.txt create mode 100644 backend/src/llvm/GenBackend.cpp create mode 100644 backend/src/llvm/GenTargetMachine.h create mode 100644 backend/src/llvm/Makefile create mode 100644 backend/src/llvm/TargetInfo/.GenBackendTargetInfo.cpp.swp create mode 100644 backend/src/llvm/TargetInfo/CMakeLists.txt create mode 100644 backend/src/llvm/TargetInfo/GenBackendTargetInfo.cpp create mode 100644 backend/src/llvm/TargetInfo/Makefile diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index cf5f5aa..d235af9 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -14,6 +14,11 @@ set (GBE_COMPILE_UTESTS false CACHE bool "Will compile the unit tests") set (GBE_USE_BLOB false CACHE bool "Compile everything from one big file") ############################################################## +# Front end stuff we need +############################################################## +Find_Package(LLVM REQUIRED) + +############################################################## # Compiler ############################################################## if (UNIX) diff --git a/backend/kernels/k b/backend/kernels/k new file mode 100644 index 0000000000000000000000000000000000000000..e48c2de7ae358fc496a26a2fa7500f78bda9f49c GIT binary patch literal 368 zcmZ>AK5$Qwhk+rIfq{WhfPp~>NV7L8Pjo!N;>jjpWI2hkg-4Z@LsE{VJE?)kmC0!m zw^NFMk%$F{geRAgi;4%=1V!Z|K@B{TibX2yCr$_?tyr+a;n)X8pgEor3=Awln!AHR z#ZiEz^FI*CAK+l2Z|dho#0SNZE9gqbN1lmRC7MY>8z-!GJ{7_oa5vS1q(NZ zXB-CS=mOiz1on~z>}3w@RY1lCwr8l^cLMBH4eV6{>}3!wKv@G9!vIDGCZMAfcv#qh zlrRfp8#B-o%s@7KfWTRiL@@ymAR7cKf&K!iG3IEHIr2~@O@z_5!`Y(caF0_1du0WC XF-T3J0z@y{1P`FIFYD`o1c3km1ISrE literal 0 HcmV?d00001 diff --git a/backend/kernels/k.ll b/backend/kernels/k.ll new file mode 100644 index 0000000..dac3a71 --- /dev/null +++ b/backend/kernels/k.ll @@ -0,0 +1,10 @@ +; ModuleID = 'k' +target datalayout = "e-p:32:32-i64:64:64-f64:64:64-n1:8:16:32:64" +target triple = "ptx32--" + +%struct.my_struct = type { i32, [2 x i32] } + +define ptx_device void @struct_cl(%struct.my_struct* nocapture byval %s) nounwind readnone { +entry: + ret void +} diff --git a/backend/kernels/k.s b/backend/kernels/k.s new file mode 100644 index 0000000..0756a2e --- /dev/null +++ b/backend/kernels/k.s @@ -0,0 +1,11 @@ + .version 2.0 + .target compute_10, map_f64_to_f32 + + +.func () struct_cl (.reg .b32 %param0) // @struct_cl +{ + +// BB#0: // %entry + ret; +} + diff --git a/backend/kernels/stdlib.h b/backend/kernels/stdlib.h new file mode 100644 index 0000000..bab425d --- /dev/null +++ b/backend/kernels/stdlib.h @@ -0,0 +1,204 @@ +/* + * Copyright © 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Benjamin Segovia + */ + +#pragma OPENCL EXTENSION cl_khr_fp64 : enable + +/* Types */ + +/* Standard types from Clang's stddef and stdint, Copyright (C) 2008 Eli Friedman */ +typedef signed __INT64_TYPE__ int64_t; +typedef unsigned __INT64_TYPE__ uint64_t; +typedef signed __INT32_TYPE__ int32_t; +typedef unsigned __INT32_TYPE__ uint32_t; +typedef signed __INT16_TYPE__ int16_t; +typedef unsigned __INT16_TYPE__ uint16_t; +typedef signed __INT8_TYPE__ int8_t; +typedef unsigned __INT8_TYPE__ uint8_t; + +#define __stdint_join3(a,b,c) a ## b ## c +#define __intn_t(n) __stdint_join3( int, n, _t) +#define __uintn_t(n) __stdint_join3(uint, n, _t) + +typedef __typeof__(((int*)0)-((int*)0)) ptrdiff_t; +typedef __typeof__(sizeof(int)) size_t; +typedef __intn_t(__INTPTR_WIDTH__) intptr_t; +typedef __uintn_t(__INTPTR_WIDTH__) uintptr_t; + +/* OpenCL types */ +typedef uint8_t uchar; +typedef uint16_t ushort; +typedef uint32_t uint; +typedef uint64_t ulong; + +typedef unsigned int sampler_t; +typedef struct image2d *image2d_t; +typedef struct image3d *image3d_t; + +/* Vectors */ +#define COAL_VECTOR(type, len) \ + typedef type type##len __attribute__((ext_vector_type(len))) +#define COAL_VECTOR_SET(type) \ + COAL_VECTOR(type, 2); \ + COAL_VECTOR(type, 3); \ + COAL_VECTOR(type, 4); \ + COAL_VECTOR(type, 8); \ + COAL_VECTOR(type, 16); + +COAL_VECTOR_SET(char) +COAL_VECTOR_SET(uchar) + +COAL_VECTOR_SET(short) +COAL_VECTOR_SET(ushort) + +COAL_VECTOR_SET(int) +COAL_VECTOR_SET(uint) + +COAL_VECTOR_SET(long) +COAL_VECTOR_SET(ulong) + +COAL_VECTOR_SET(float) + +#undef COAL_VECTOR_SET +#undef COAL_VECTOR + +/* Address spaces */ +#define __private __attribute__((address_space(0))) +#define __global __attribute__((address_space(1))) +#define __local __attribute__((address_space(2))) +#define __constant __attribute__((address_space(3))) + +#define global __global +#define local __local +#define constant __constant +#define private __private + +#define __write_only +#define __read_only const + +#define write_only __write_only +#define read_only __read_only + +/* Defines */ +#define OVERLOAD __attribute__((overloadable)) + +#define CLK_NORMALIZED_COORDS_FALSE 0x00000000 +#define CLK_NORMALIZED_COORDS_TRUE 0x00000001 +#define CLK_ADDRESS_NONE 0x00000000 +#define CLK_ADDRESS_MIRRORED_REPEAT 0x00000010 +#define CLK_ADDRESS_REPEAT 0x00000020 +#define CLK_ADDRESS_CLAMP_TO_EDGE 0x00000030 +#define CLK_ADDRESS_CLAMP 0x00000040 +#define CLK_FILTER_NEAREST 0x00000000 +#define CLK_FILTER_LINEAR 0x00000100 + +#define CLK_LOCAL_MEM_FENCE 0x00000001 +#define CLK_GLOBAL_MEM_FENCE 0x00000002 + +#define CLK_R 0x10B0 +#define CLK_A 0x10B1 +#define CLK_RG 0x10B2 +#define CLK_RA 0x10B3 +#define CLK_RGB 0x10B4 +#define CLK_RGBA 0x10B5 +#define CLK_BGRA 0x10B6 +#define CLK_ARGB 0x10B7 +#define CLK_INTENSITY 0x10B8 +#define CLK_LUMINANCE 0x10B9 +#define CLK_Rx 0x10BA +#define CLK_RGx 0x10BB +#define CLK_RGBx 0x10BC + +#define CLK_SNORM_INT8 0x10D0 +#define CLK_SNORM_INT16 0x10D1 +#define CLK_UNORM_INT8 0x10D2 +#define CLK_UNORM_INT16 0x10D3 +#define CLK_UNORM_SHORT_565 0x10D4 +#define CLK_UNORM_SHORT_555 0x10D5 +#define CLK_UNORM_INT_101010 0x10D6 +#define CLK_SIGNED_INT8 0x10D7 +#define CLK_SIGNED_INT16 0x10D8 +#define CLK_SIGNED_INT32 0x10D9 +#define CLK_UNSIGNED_INT8 0x10DA +#define CLK_UNSIGNED_INT16 0x10DB +#define CLK_UNSIGNED_INT32 0x10DC +#define CLK_HALF_FLOAT 0x10DD +#define CLK_FLOAT 0x10DE + +#define M_E 2.7182818284590452354 /* e */ +#define M_LOG2E 1.4426950408889634074 /* log_2 e */ +#define M_LOG10E 0.43429448190325182765 /* log_10 e */ +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#define M_PI 3.14159265358979323846 /* pi */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_PI_4 0.78539816339744830962 /* pi/4 */ +#define M_1_PI 0.31830988618379067154 /* 1/pi */ +#define M_2_PI 0.63661977236758134308 /* 2/pi */ +#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ + +/* Typedefs */ +typedef unsigned int cl_mem_fence_flags; + +/* Management functions */ +uint get_work_dim(); +size_t get_global_size(uint dimindx); +size_t get_global_id(uint dimindx); +size_t get_local_size(uint dimindx); +size_t get_local_id(uint dimindx); +size_t get_num_groups(uint dimindx); +size_t get_group_id(uint dimindx); +size_t get_global_offset(uint dimindx); + +void barrier(cl_mem_fence_flags flags); + +/* Image functions */ +float4 OVERLOAD read_imagef(image2d_t image, sampler_t sampler, int2 coord); +float4 OVERLOAD read_imagef(image3d_t image, sampler_t sampler, int4 coord); +float4 OVERLOAD read_imagef(image2d_t image, sampler_t sampler, float2 coord); +float4 OVERLOAD read_imagef(image3d_t image, sampler_t sampler, float4 coord); +int4 OVERLOAD read_imagei(image2d_t image, sampler_t sampler, int2 coord); +int4 OVERLOAD read_imagei(image3d_t image, sampler_t sampler, int4 coord); +int4 OVERLOAD read_imagei(image2d_t image, sampler_t sampler, float2 coord); +int4 OVERLOAD read_imagei(image3d_t image, sampler_t sampler, float4 coord); +uint4 OVERLOAD read_imageui(image2d_t image, sampler_t sampler, int2 coord); +uint4 OVERLOAD read_imageui(image3d_t image, sampler_t sampler, int4 coord); +uint4 OVERLOAD read_imageui(image2d_t image, sampler_t sampler, float2 coord); +uint4 OVERLOAD read_imageui(image3d_t image, sampler_t sampler, float4 coord); + +void OVERLOAD write_imagef(image2d_t image, int2 coord, float4 color); +void OVERLOAD write_imagef(image3d_t image, int4 coord, float4 color); +void OVERLOAD write_imagei(image2d_t image, int2 coord, int4 color); +void OVERLOAD write_imagei(image3d_t image, int4 coord, int4 color); +void OVERLOAD write_imageui(image2d_t image, int2 coord, uint4 color); +void OVERLOAD write_imageui(image3d_t image, int4 coord, uint4 color); + +int2 OVERLOAD get_image_dim(image2d_t image); +int4 OVERLOAD get_image_dim(image3d_t image); +int OVERLOAD get_image_width(image2d_t image); +int OVERLOAD get_image_width(image3d_t image); +int OVERLOAD get_image_height(image2d_t image); +int OVERLOAD get_image_height(image3d_t image); +int OVERLOAD get_image_depth(image3d_t image); + +int OVERLOAD get_image_channel_data_type(image2d_t image); +int OVERLOAD get_image_channel_data_type(image3d_t image); +int OVERLOAD get_image_channel_order(image2d_t image); +int OVERLOAD get_image_channel_order(image3d_t image); diff --git a/backend/kernels/struct.cl b/backend/kernels/struct.cl new file mode 100644 index 0000000..b9ec661 --- /dev/null +++ b/backend/kernels/struct.cl @@ -0,0 +1,10 @@ +struct my_struct { + int a; + int b[2]; +}; + +void struct_cl (struct my_struct s) +{ + +} + diff --git a/backend/kernels/struct.cl.o b/backend/kernels/struct.cl.o new file mode 100644 index 0000000000000000000000000000000000000000..424f97661acfa7443fb8af2e59e8b4a8b9c5ef11 GIT binary patch literal 592 zcmZ>AK5$Qwhk;=t0|Nu200V;%kY;aGp6Gaj#gk3I$Z`^63y&%*hol@!cTxk7E0fbC zZl@FhBM}P@2~RE~7Zne#35v=`f*N=v6^m5ZPn-})TCre-!?6#HKyy4L7#LW9Gu!pgwVsldPhw35L{=>&&DYEuh?nzIKdr<(IIPG?0;l^Hye;v6SuC>Xdg zJmYXk>|@|L)zD!EbQ*)OLCpbX>mRJv3!2SVu$M=$mshk`7qputw3igLR~=|KvtTb@ z(avia$d}8&UzNaKvVgtJfgQxS!1hvry{Z9(awqUrEMNyAuwdB&_QC}ADgpK~AlHDs zXaRe%0(%vZ0py~Z@C;S<8LI3zG_C-95zsm$GFO1FU;#T20iBd*=9|3_tVp8R1dn|W1SUFMP=hkA0Hwg7 z5*TkFb;cYGGDjZDq=_)vb~szK9PV*yV6UuTF9sAK5$Qwhk>D!fq{WhfPp~>NV7L8Pjo!N;>jjpWI2hkg-4Z@LsE{VJE?)kmC0!m zw^NFMk%$F{geRAgi;4%=1V!Z|K@B{TibX2yCr$_?tyr+a;n)X8pgEor3=Awln!Dvc z5Xc{pU~v>+VFlWyz`(!-6gN^j!J&}a)WV?V?7_*Y=6sCPSy5AE29KmT$H^HA3T_Nu z45u7`>Vyqy4lrB)V6|S*Y_@{EJc7NvqP@DH-7KNKq@ca(K)aa*d-;lXUc*4XTn7HC z1on~z>}3w@AjSo@mjdin4Iq>|fv;i#I|zXV%NDQ~Ca_ltu$KY32JA%(*ozg|tAGq3 z7uAGksIt#cWxt_u1=x##)*+F(0(=Dv*ntS>q+A1j2m|7_XAL0nLIsekK;#9scVN9h zw}Bi3cK>FuQO+Wa3=P1LU^sCYNN@nLGYg}{!#&J4Q<|-Nn5}mlw3^avv%}eP!(kgA zPLRSx1qKE-AT7+o*v1Tu3??9(JwV{BNFtB{1eL(JVF%L291Su@9?GPNFxqxFTeKYR aacW?%tY9w&sVP)|=wmaGImZkV00IE6wU-qD literal 0 HcmV?d00001 diff --git a/backend/kernels/void.cl.o.cbe.c b/backend/kernels/void.cl.o.cbe.c new file mode 100644 index 0000000..adb99b8 --- /dev/null +++ b/backend/kernels/void.cl.o.cbe.c @@ -0,0 +1,157 @@ +/* + * Copyright © 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Benjamin Segovia + */ + +/* Provide Declarations */ +#include +#include +#include +/* 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 +#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 + +#define CODE_FOR_MAIN() /* Any target-specific code for main()*/ + +#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 */ +/* Helper union for bitcasts */ +typedef union { + unsigned int Int32; + unsigned long long Int64; + float Float; + double Double; +} llvmBitCastUnion; + +/* Function Declarations */ +double fmod(double, double); +float fmodf(float, float); +long double fmodl(long double, long double); +void hop(void); +void abort(void); + + +/* 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 ; } + +void hop(void) { + return; +} + diff --git a/backend/kernels/void.cl.o.ll b/backend/kernels/void.cl.o.ll new file mode 100644 index 0000000..28fb111 --- /dev/null +++ b/backend/kernels/void.cl.o.ll @@ -0,0 +1,12 @@ +; ModuleID = 'void.cl.o' +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-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @hop() nounwind uwtable readnone { +entry: + ret void +} + +!opencl.kernels = !{!0} + +!0 = metadata !{void ()* @hop} diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt index cbf34d6..02171c8 100644 --- a/backend/src/CMakeLists.txt +++ b/backend/src/CMakeLists.txt @@ -1,3 +1,6 @@ +add_subdirectory(llvm) +add_subdirectory(llc) + if (GBE_USE_BLOB) set (GBE_SRC blob.cpp) else (GBE_USE_BLOB) @@ -48,6 +51,10 @@ endif (GBE_USE_BLOB) include_directories (.) add_library (gbe SHARED ${GBE_SRC}) +link_directories (${LLVM_LIBRARY_DIRS}) + +include (${LLVM_DIR}/AddLLVMDefinitions.cmake) +target_link_libraries (gbe llc) if (GBE_COMPILE_UTESTS) set (TESTER_SRC utest/tester.cpp) diff --git a/backend/src/llc/.CMakeLists.txt.swp b/backend/src/llc/.CMakeLists.txt.swp new file mode 100644 index 0000000000000000000000000000000000000000..f307d260a57f624fe89a8f8bbac2e667a82d6d96 GIT binary patch literal 12288 zcmeI&OODep7zc0R3KDF;t;Up z1e}430B7M#Ns&M(WmagUzooBM>VN(CNnKQRbTsq&{IqexsNG_0^}Q3ke|f+@J!UMj zYM!mMD2A%qHg~8`kE(L-w!x+~adWQH!$`ynmCDU?lElqUUo4cbt+NgH+EvYkF$h55 zvI5uH$?>Djcl6%f1AgcB^s*Bm4*>{300Izz00bZa0SH`S0hjNw3)=s+@(lZBzxPL9 zKB9vF1Rwwb2tWV=5P$##AOHafK;Q}r2+7#&24f$nivRz&zyH79Wb8B51=W!10o6Ck ze4+YS<{kCVsh&|iq}r!Kg8&2|009U<00Izz00bZaf&V7pgqbTBCOTcvOJs!6%JLfB zw?5{+KkJ{Vv@K$`GqyXinW(tXU1w~woYY3eF8jIQ{kO$xq3>0VwMVVdi*R?M>y5_i zIulZcNwQj&2YXYTic>Y>Jg+mW9Ius&4xWacpg#--y}@M6%e_omqqE**98Q9;J@x$V znn&6hC8RQ3*kvw^Ri@5#8Ykycg?~GaH|Y4&ZZ9l1R7QENT!G$RH;XL{O%^L_$Jx1| pz7a3!ru(m%e~&*AsZ3Pyp&)lUORLi@DT`=Vz0#@v=lFI5KL89!. + * + * Author: Benjamin Segovia + */ + +//===-- llc.cpp - Implement the LLVM Native Code Generator ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the llc code generator driver. It provides a convenient +// command-line interface for generating native assembly-language code +// or C code, given LLVM bitcode. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/IRReader.h" +#include "llvm/CodeGen/LinkAllAsmWriterComponents.h" +#include "llvm/CodeGen/LinkAllCodegenComponents.h" +#include "llvm/Config/config.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PluginLoader.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include +using namespace llvm; + +// General options for llc. Other pass-specific options are specified +// within the corresponding llc passes, and target-specific options +// and back-end code generation options are specified with the target machine. +// +static cl::opt +InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + +static cl::opt +OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); + +// Determine optimization level. +static cl::opt +OptLevel("O", + cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " + "(default = '-O2')"), + cl::Prefix, + cl::ZeroOrMore, + cl::init(' ')); + +static cl::opt +TargetTriple("mtriple", cl::desc("Override target triple for module")); + +static cl::opt +MArch("march", cl::desc("Architecture to generate code for (see --version)")); + +static cl::opt +MCPU("mcpu", + cl::desc("Target a specific cpu type (-mcpu=help for details)"), + cl::value_desc("cpu-name"), + cl::init("")); + +static cl::list +MAttrs("mattr", + cl::CommaSeparated, + cl::desc("Target specific attributes (-mattr=help for details)"), + cl::value_desc("a1,+a2,-a3,...")); + +static cl::opt +RelocModel("relocation-model", + cl::desc("Choose relocation model"), + cl::init(Reloc::Default), + cl::values( + clEnumValN(Reloc::Default, "default", + "Target default relocation model"), + clEnumValN(Reloc::Static, "static", + "Non-relocatable code"), + clEnumValN(Reloc::PIC_, "pic", + "Fully relocatable, position independent code"), + clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic", + "Relocatable external references, non-relocatable code"), + clEnumValEnd)); + +static cl::opt +CMModel("code-model", + cl::desc("Choose code model"), + cl::init(CodeModel::Default), + cl::values(clEnumValN(CodeModel::Default, "default", + "Target default code model"), + clEnumValN(CodeModel::Small, "small", + "Small code model"), + clEnumValN(CodeModel::Kernel, "kernel", + "Kernel code model"), + clEnumValN(CodeModel::Medium, "medium", + "Medium code model"), + clEnumValN(CodeModel::Large, "large", + "Large code model"), + clEnumValEnd)); + +static cl::opt +RelaxAll("mc-relax-all", + cl::desc("When used with filetype=obj, " + "relax all fixups in the emitted object file")); + +cl::opt +FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile), + cl::desc("Choose a file type (not all types are supported by all targets):"), + cl::values( + clEnumValN(TargetMachine::CGFT_AssemblyFile, "asm", + "Emit an assembly ('.s') file"), + clEnumValN(TargetMachine::CGFT_ObjectFile, "obj", + "Emit a native object ('.o') file [experimental]"), + clEnumValN(TargetMachine::CGFT_Null, "null", + "Emit nothing, for performance testing"), + clEnumValEnd)); + +cl::opt NoVerify("disable-verify", cl::Hidden, + cl::desc("Do not verify input module")); + +cl::opt DisableDotLoc("disable-dot-loc", cl::Hidden, + cl::desc("Do not use .loc entries")); + +cl::opt DisableCFI("disable-cfi", cl::Hidden, + cl::desc("Do not use .cfi_* directives")); + +static cl::opt +DisableRedZone("disable-red-zone", + cl::desc("Do not emit code that uses the red zone."), + cl::init(false)); + +// GetFileNameRoot - Helper function to get the basename of a filename. +static inline std::string +GetFileNameRoot(const std::string &InputFilename) { + std::string IFN = InputFilename; + std::string outputFilename; + int Len = IFN.length(); + if ((Len > 2) && + IFN[Len-3] == '.' && + ((IFN[Len-2] == 'b' && IFN[Len-1] == 'c') || + (IFN[Len-2] == 'l' && IFN[Len-1] == 'l'))) { + outputFilename = std::string(IFN.begin(), IFN.end()-3); // s/.bc/.s/ + } else { + outputFilename = IFN; + } + return outputFilename; +} + +static tool_output_file *GetOutputStream(const char *TargetName, + Triple::OSType OS, + const char *ProgName) { + // If we don't yet have an output filename, make one. + if (OutputFilename.empty()) { + if (InputFilename == "-") + OutputFilename = "-"; + else { + OutputFilename = GetFileNameRoot(InputFilename); + + switch (FileType) { + default: assert(0 && "Unknown file type"); + case TargetMachine::CGFT_AssemblyFile: + if (TargetName[0] == 'c') { + if (TargetName[1] == 0) + OutputFilename += ".cbe.c"; + else if (TargetName[1] == 'p' && TargetName[2] == 'p') + OutputFilename += ".cpp"; + else + OutputFilename += ".s"; + } else + OutputFilename += ".s"; + break; + case TargetMachine::CGFT_ObjectFile: + if (OS == Triple::Win32) + OutputFilename += ".obj"; + else + OutputFilename += ".o"; + break; + case TargetMachine::CGFT_Null: + OutputFilename += ".null"; + break; + } + } + } + + // Decide if we need "binary" output. + bool Binary = false; + switch (FileType) { + default: assert(0 && "Unknown file type"); + case TargetMachine::CGFT_AssemblyFile: + break; + case TargetMachine::CGFT_ObjectFile: + case TargetMachine::CGFT_Null: + Binary = true; + break; + } + + // Open the file. + std::string error; + unsigned OpenFlags = 0; + if (Binary) OpenFlags |= raw_fd_ostream::F_Binary; + tool_output_file *FDOut = new tool_output_file(OutputFilename.c_str(), error, + OpenFlags); + if (!error.empty()) { + errs() << error << '\n'; + delete FDOut; + return 0; + } + + return FDOut; +} +extern "C" void LLVMInitializeGenBackendTarget(); +extern "C" void LLVMInitializeGenBackendTargetInfo(); + +extern "C" int llvmToGen(int argc, char **argv) +{ + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + // Enable debug stream buffering. + EnableDebugBuffering = true; + + LLVMContext &Context = getGlobalContext(); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize targets first, so that --version shows registered targets. + LLVMInitializeGenBackendTarget(); + LLVMInitializeGenBackendTargetInfo(); + InitializeAllTargetMCs(); + InitializeAllAsmPrinters(); + InitializeAllAsmParsers(); + + // Register the target printer for --version. + cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); + + cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); + + // Load the module to be compiled... + SMDiagnostic Err; + std::auto_ptr M; + + M.reset(ParseIRFile(InputFilename, Err, Context)); + if (M.get() == 0) { + Err.Print(argv[0], errs()); + return 1; + } + Module &mod = *M.get(); + + // If we are supposed to override the target triple, do so now. + if (!TargetTriple.empty()) + mod.setTargetTriple(Triple::normalize(TargetTriple)); + + Triple TheTriple(mod.getTargetTriple()); + if (TheTriple.getTriple().empty()) + TheTriple.setTriple(sys::getHostTriple()); + + // Allocate target machine. First, check whether the user has explicitly + // specified an architecture to compile for. If so we have to look it up by + // name, because it might be a backend that has no mapping to a target triple. + const Target *TheTarget = 0; + if (!MArch.empty()) { + for (TargetRegistry::iterator it = TargetRegistry::begin(), + ie = TargetRegistry::end(); it != ie; ++it) { + if (MArch == it->getName()) { + TheTarget = &*it; + break; + } + } + + if (!TheTarget) { + errs() << argv[0] << ": error: invalid target '" << MArch << "'.\n"; + return 1; + } + + // Adjust the triple to match (if known), otherwise stick with the + // module/host triple. + Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch); + if (Type != Triple::UnknownArch) + TheTriple.setArch(Type); + } else { + std::string Err; + TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Err); + if (TheTarget == 0) { + errs() << argv[0] << ": error auto-selecting target for module '" + << Err << "'. Please use the -march option to explicitly " + << "pick a target.\n"; + return 1; + } + } + + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + if (MAttrs.size()) { + SubtargetFeatures Features; + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + FeaturesStr = Features.getString(); + } + + std::auto_ptr + target(TheTarget->createTargetMachine(TheTriple.getTriple(), + MCPU, FeaturesStr, + RelocModel, CMModel)); + assert(target.get() && "Could not allocate target machine!"); + TargetMachine &Target = *target.get(); + + if (DisableDotLoc) + Target.setMCUseLoc(false); + + if (DisableCFI) + Target.setMCUseCFI(false); + + // Disable .loc support for older OS X versions. + if (TheTriple.isMacOSX() && + TheTriple.isMacOSXVersionLT(10, 6)) + Target.setMCUseLoc(false); + + // Figure out where we are going to send the output... + OwningPtr Out + (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0])); + if (!Out) return 1; + + CodeGenOpt::Level OLvl = CodeGenOpt::Default; + switch (OptLevel) { + default: + errs() << argv[0] << ": invalid optimization level.\n"; + return 1; + case ' ': break; + case '0': OLvl = CodeGenOpt::None; break; + case '1': OLvl = CodeGenOpt::Less; break; + case '2': OLvl = CodeGenOpt::Default; break; + case '3': OLvl = CodeGenOpt::Aggressive; break; + } + + // Build up all of the passes that we want to do to the module. + PassManager PM; + + // Add the target data from the target machine, if it exists, or the module. + if (const TargetData *TD = Target.getTargetData()) + PM.add(new TargetData(*TD)); + else + PM.add(new TargetData(&mod)); + + // Override default to generate verbose assembly. + Target.setAsmVerbosityDefault(true); + + if (RelaxAll) { + if (FileType != TargetMachine::CGFT_ObjectFile) + errs() << argv[0] + << ": warning: ignoring -mc-relax-all because filetype != obj"; + else + Target.setMCRelaxAll(true); + } + + { + formatted_raw_ostream FOS(Out->os()); + + // Ask the target to add backend passes as necessary. + if (Target.addPassesToEmitFile(PM, FOS, FileType, OLvl, NoVerify)) { + errs() << argv[0] << ": target does not support generation of this" + << " file type!\n"; + return 1; + } + + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + + PM.run(mod); + } + + // Declare success. + Out->keep(); + + return 0; +} + diff --git a/backend/src/llvm/.GenBackend.cpp.swp b/backend/src/llvm/.GenBackend.cpp.swp new file mode 100644 index 0000000000000000000000000000000000000000..eed2e6acf2dfec32514ae9228dcddbcb195c210a GIT binary patch literal 147456 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 L3c||Yp67o9PW2h^ literal 0 HcmV?d00001 diff --git a/backend/src/llvm/CMakeLists.txt b/backend/src/llvm/CMakeLists.txt new file mode 100644 index 0000000..10745c5 --- /dev/null +++ b/backend/src/llvm/CMakeLists.txt @@ -0,0 +1,20 @@ +include (${LLVM_DIR}/AddLLVM.cmake) +include (${LLVM_DIR}/AddLLVMDefinitions.cmake) +include (${LLVM_DIR}/HandleLLVMOptions.cmake) +include (${LLVM_DIR}/LLVMProcessSources.cmake) +include_directories(${LLVM_INCLUDE_DIRS}) +add_llvm_target(GenBackend GenBackend.cpp) + +add_llvm_library_dependencies(LLVMGenBackend + LLVMAnalysis + LLVMGenBackendInfo + LLVMCodeGen + LLVMCore + LLVMMC + LLVMScalarOpts + LLVMSupport + LLVMTarget + LLVMTransformUtils) + +add_subdirectory(TargetInfo) + diff --git a/backend/src/llvm/GenBackend.cpp b/backend/src/llvm/GenBackend.cpp new file mode 100644 index 0000000..df47b5b --- /dev/null +++ b/backend/src/llvm/GenBackend.cpp @@ -0,0 +1,3638 @@ +/* + * Copyright © 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Benjamin Segovia + */ + +//===-- CBackend.cpp - Library for converting LLVM code to C --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This library converts LLVM code to C code, compilable by GCC and other C +// compilers. +// +//===----------------------------------------------------------------------===// + +#include "GenTargetMachine.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/PassManager.h" +#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/InlineAsm.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/ConstantsScanner.h" +#include "llvm/Analysis/FindUsedTypes.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/Host.h" +#include "llvm/Config/config.h" +#include +// Some ms header decided to define setjmp as _setjmp, undo this for this file. +#ifdef _MSC_VER +#undef setjmp +#endif +using namespace llvm; + +extern "C" void LLVMInitializeGenBackendTarget() { + // Register the target. + RegisterTargetMachine X(TheGenBackendTarget); +} + +namespace { + class CBEMCAsmInfo : public MCAsmInfo { + public: + CBEMCAsmInfo() { + GlobalPrefix = ""; + PrivateGlobalPrefix = ""; + } + }; + + /// GenWriter - This class is the main chunk of code that converts an LLVM + /// module to a C translation unit. + class GenWriter : public FunctionPass, public InstVisitor { + formatted_raw_ostream &Out; + IntrinsicLowering *IL; + Mangler *Mang; + LoopInfo *LI; + const Module *TheModule; + const MCAsmInfo* TAsm; + const MCRegisterInfo *MRI; + const MCObjectFileInfo *MOFI; + MCContext *TCtx; + const TargetData* TD; + + std::map FPConstantMap; + std::set intrinsicPrototypesAlreadyGenerated; + std::set ByValParams; + unsigned FPCounter; + unsigned OpaqueCounter; + DenseMap AnonValueNumbers; + unsigned NextAnonValueNumber; + + /// UnnamedStructIDs - This contains a unique ID for each struct that is + /// either anonymous or has no name. + DenseMap UnnamedStructIDs; + + public: + static char ID; + explicit GenWriter(formatted_raw_ostream &o) + : FunctionPass(ID), Out(o), IL(0), Mang(0), LI(0), + TheModule(0), TAsm(0), MRI(0), MOFI(0), TCtx(0), TD(0), + OpaqueCounter(0), NextAnonValueNumber(0) { + initializeLoopInfoPass(*PassRegistry::getPassRegistry()); + FPCounter = 0; + printf("DDDn\n\n"); + } + + virtual const char *getPassName() const { return "Gen backend"; } + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.setPreservesAll(); + } + + virtual bool doInitialization(Module &M); + + bool runOnFunction(Function &F) { + // Do not codegen any 'available_externally' functions at all, they have + // definitions outside the translation unit. + if (F.hasAvailableExternallyLinkage()) + return false; + + LI = &getAnalysis(); + + // Get rid of intrinsics we can't handle. + lowerIntrinsics(F); + + // Output all floating point constants that cannot be printed accurately. + printFloatingPointConstants(F); + + printFunction(F); + return false; + } + + virtual bool doFinalization(Module &M) { + // Free memory... + delete IL; + delete TD; + delete Mang; + delete TCtx; + delete TAsm; + delete MRI; + delete MOFI; + FPConstantMap.clear(); + ByValParams.clear(); + intrinsicPrototypesAlreadyGenerated.clear(); + UnnamedStructIDs.clear(); + return false; + } + + raw_ostream &printType(raw_ostream &Out, Type *Ty, + bool isSigned = false, + const std::string &VariableName = "", + bool IgnoreName = false, + const AttrListPtr &PAL = AttrListPtr()); + raw_ostream &printSimpleType(raw_ostream &Out, Type *Ty, + bool isSigned, + const std::string &NameSoFar = ""); + + void printStructReturnPointerFunctionType(raw_ostream &Out, + const AttrListPtr &PAL, + PointerType *Ty); + + std::string getStructName(StructType *ST); + + /// writeOperandDeref - Print the result of dereferencing the specified + /// operand with '*'. This is equivalent to printing '*' then using + /// writeOperand, but avoids excess syntax in some cases. + void writeOperandDeref(Value *Operand) { + if (isAddressExposed(Operand)) { + // Already something with an address exposed. + writeOperandInternal(Operand); + } else { + Out << "*("; + writeOperand(Operand); + Out << ")"; + } + } + + void writeOperand(Value *Operand, bool Static = false); + void writeInstComputationInline(Instruction &I); + void writeOperandInternal(Value *Operand, bool Static = false); + void writeOperandWithCast(Value* Operand, unsigned Opcode); + void writeOperandWithCast(Value* Operand, const ICmpInst &I); + bool writeInstructionCast(const Instruction &I); + + void writeMemoryAccess(Value *Operand, Type *OperandType, + bool IsVolatile, unsigned Alignment); + + private : + std::string InterpretASMConstraint(InlineAsm::ConstraintInfo& c); + + void lowerIntrinsics(Function &F); + /// Prints the definition of the intrinsic function F. Supports the + /// intrinsics which need to be explicitly defined in the CBackend. + void printIntrinsicDefinition(const Function &F, raw_ostream &Out); + + void printModuleTypes(); + void printContainedStructs(Type *Ty, SmallPtrSet &); + void printFloatingPointConstants(Function &F); + void printFloatingPointConstants(const Constant *C); + void printFunctionSignature(const Function *F, bool Prototype); + + void printFunction(Function &); + void printBasicBlock(BasicBlock *BB); + void printLoop(Loop *L); + + void printCast(unsigned opcode, Type *SrcTy, Type *DstTy); + void printConstant(Constant *CPV, bool Static); + void printConstantWithCast(Constant *CPV, unsigned Opcode); + bool printConstExprCast(const ConstantExpr *CE, bool Static); + void printConstantArray(ConstantArray *CPA, bool Static); + void printConstantVector(ConstantVector *CV, bool Static); + + /// isAddressExposed - Return true if the specified value's name needs to + /// have its address taken in order to get a C value of the correct type. + /// This happens for global variables, byval parameters, and direct allocas. + bool isAddressExposed(const Value *V) const { + if (const Argument *A = dyn_cast(V)) + return ByValParams.count(A); + return isa(V) || isDirectAlloca(V); + } + + // isInlinableInst - Attempt to inline instructions into their uses to build + // trees as much as possible. To do this, we have to consistently decide + // what is acceptable to inline, so that variable declarations don't get + // printed and an extra copy of the expr is not emitted. + // + static bool isInlinableInst(const Instruction &I) { + // Always inline cmp instructions, even if they are shared by multiple + // expressions. GCC generates horrible code if we don't. + if (isa(I)) + return true; + + // Must be an expression, must be used exactly once. If it is dead, we + // emit it inline where it would go. + if (I.getType() == Type::getVoidTy(I.getContext()) || !I.hasOneUse() || + isa(I) || isa(I) || isa(I) || + isa(I) || isa(I) || isa(I) || + isa(I)) + // Don't inline a load across a store or other bad things! + return false; + + // Must not be used in inline asm, extractelement, or shufflevector. + if (I.hasOneUse()) { + const Instruction &User = cast(*I.use_back()); + if (isInlineAsm(User) || isa(User) || + isa(User)) + return false; + } + + // Only inline instruction it if it's use is in the same BB as the inst. + return I.getParent() == cast(I.use_back())->getParent(); + } + + // isDirectAlloca - Define fixed sized allocas in the entry block as direct + // variables which are accessed with the & operator. This causes GCC to + // generate significantly better code than to emit alloca calls directly. + // + static const AllocaInst *isDirectAlloca(const Value *V) { + const AllocaInst *AI = dyn_cast(V); + if (!AI) return 0; + if (AI->isArrayAllocation()) + return 0; // FIXME: we can also inline fixed size array allocas! + if (AI->getParent() != &AI->getParent()->getParent()->getEntryBlock()) + return 0; + return AI; + } + + // isInlineAsm - Check if the instruction is a call to an inline asm chunk. + static bool isInlineAsm(const Instruction& I) { + if (const CallInst *CI = dyn_cast(&I)) + return isa(CI->getCalledValue()); + return false; + } + + // Instruction visitation functions + friend class InstVisitor; + + void visitReturnInst(ReturnInst &I); + void visitBranchInst(BranchInst &I); + void visitSwitchInst(SwitchInst &I); + void visitIndirectBrInst(IndirectBrInst &I); + void visitInvokeInst(InvokeInst &I) { + llvm_unreachable("Lowerinvoke pass didn't work!"); + } + void visitUnwindInst(UnwindInst &I) { + llvm_unreachable("Lowerinvoke pass didn't work!"); + } + void visitResumeInst(ResumeInst &I) { + llvm_unreachable("DwarfEHPrepare pass didn't work!"); + } + void visitUnreachableInst(UnreachableInst &I); + + void visitPHINode(PHINode &I); + void visitBinaryOperator(Instruction &I); + void visitICmpInst(ICmpInst &I); + void visitFCmpInst(FCmpInst &I); + + void visitCastInst (CastInst &I); + void visitSelectInst(SelectInst &I); + void visitCallInst (CallInst &I); + void visitInlineAsm(CallInst &I); + bool visitBuiltinCall(CallInst &I, Intrinsic::ID ID, bool &WroteCallee); + + void visitAllocaInst(AllocaInst &I); + void visitLoadInst (LoadInst &I); + void visitStoreInst (StoreInst &I); + void visitGetElementPtrInst(GetElementPtrInst &I); + void visitVAArgInst (VAArgInst &I); + + void visitInsertElementInst(InsertElementInst &I); + void visitExtractElementInst(ExtractElementInst &I); + void visitShuffleVectorInst(ShuffleVectorInst &SVI); + + void visitInsertValueInst(InsertValueInst &I); + void visitExtractValueInst(ExtractValueInst &I); + + void visitInstruction(Instruction &I) { +#ifndef NDEBUG + errs() << "C Writer does not know about " << I; +#endif + llvm_unreachable(0); + } + + void outputLValue(Instruction *I) { + Out << " " << GetValueName(I) << " = "; + } + + bool isGotoCodeNecessary(BasicBlock *From, BasicBlock *To); + void printPHICopiesForSuccessor(BasicBlock *CurBlock, + BasicBlock *Successor, unsigned Indent); + void printBranchToBlock(BasicBlock *CurBlock, BasicBlock *SuccBlock, + unsigned Indent); + void printGEPExpression(Value *Ptr, gep_type_iterator I, + gep_type_iterator E, bool Static); + + std::string GetValueName(const Value *Operand); + }; +} + +char GenWriter::ID = 0; + + + +static std::string CBEMangle(const std::string &S) { + std::string Result; + + for (unsigned i = 0, e = S.size(); i != e; ++i) + if (isalnum(S[i]) || S[i] == '_') { + Result += S[i]; + } else { + Result += '_'; + Result += 'A'+(S[i]&15); + Result += 'A'+((S[i]>>4)&15); + Result += '_'; + } + return Result; +} + +std::string GenWriter::getStructName(StructType *ST) { + if (!ST->isLiteral() && !ST->getName().empty()) + return CBEMangle("l_"+ST->getName().str()); + + return "l_unnamed_" + utostr(UnnamedStructIDs[ST]); +} + + +/// printStructReturnPointerFunctionType - This is like printType for a struct +/// return type, except, instead of printing the type as void (*)(Struct*, ...) +/// print it as "Struct (*)(...)", for struct return functions. +void GenWriter::printStructReturnPointerFunctionType(raw_ostream &Out, + const AttrListPtr &PAL, + PointerType *TheTy) { + FunctionType *FTy = cast(TheTy->getElementType()); + std::string tstr; + raw_string_ostream FunctionInnards(tstr); + FunctionInnards << " (*) ("; + bool PrintedType = false; + + FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end(); + Type *RetTy = cast(*I)->getElementType(); + unsigned Idx = 1; + for (++I, ++Idx; I != E; ++I, ++Idx) { + if (PrintedType) + FunctionInnards << ", "; + Type *ArgTy = *I; + if (PAL.paramHasAttr(Idx, Attribute::ByVal)) { + assert(ArgTy->isPointerTy()); + ArgTy = cast(ArgTy)->getElementType(); + } + printType(FunctionInnards, ArgTy, + /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt), ""); + PrintedType = true; + } + if (FTy->isVarArg()) { + if (!PrintedType) + FunctionInnards << " int"; //dummy argument for empty vararg functs + FunctionInnards << ", ..."; + } else if (!PrintedType) { + FunctionInnards << "void"; + } + FunctionInnards << ')'; + printType(Out, RetTy, + /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), FunctionInnards.str()); +} + +raw_ostream & +GenWriter::printSimpleType(raw_ostream &Out, Type *Ty, bool isSigned, + const std::string &NameSoFar) { + assert((Ty->isPrimitiveType() || Ty->isIntegerTy() || Ty->isVectorTy()) && + "Invalid type for printSimpleType"); + switch (Ty->getTypeID()) { + case Type::VoidTyID: return Out << "void " << NameSoFar; + case Type::IntegerTyID: { + unsigned NumBits = cast(Ty)->getBitWidth(); + if (NumBits == 1) + return Out << "bool " << NameSoFar; + else if (NumBits <= 8) + return Out << (isSigned?"signed":"unsigned") << " char " << NameSoFar; + else if (NumBits <= 16) + return Out << (isSigned?"signed":"unsigned") << " short " << NameSoFar; + else if (NumBits <= 32) + return Out << (isSigned?"signed":"unsigned") << " int " << NameSoFar; + else if (NumBits <= 64) + return Out << (isSigned?"signed":"unsigned") << " long long "<< NameSoFar; + else { + assert(NumBits <= 128 && "Bit widths > 128 not implemented yet"); + return Out << (isSigned?"llvmInt128":"llvmUInt128") << " " << NameSoFar; + } + } + case Type::FloatTyID: return Out << "float " << NameSoFar; + case Type::DoubleTyID: return Out << "double " << NameSoFar; + // Lacking emulation of FP80 on PPC, etc., we assume whichever of these is + // present matches host 'long double'. + case Type::X86_FP80TyID: + case Type::PPC_FP128TyID: + case Type::FP128TyID: return Out << "long double " << NameSoFar; + + case Type::X86_MMXTyID: + return printSimpleType(Out, Type::getInt32Ty(Ty->getContext()), isSigned, + " __attribute__((vector_size(64))) " + NameSoFar); + + case Type::VectorTyID: { + VectorType *VTy = cast(Ty); + return printSimpleType(Out, VTy->getElementType(), isSigned, + " __attribute__((vector_size(" + + utostr(TD->getTypeAllocSize(VTy)) + " ))) " + NameSoFar); + } + + default: +#ifndef NDEBUG + errs() << "Unknown primitive type: " << *Ty << "\n"; +#endif + llvm_unreachable(0); + } +} + +// Pass the Type* and the variable name and this prints out the variable +// declaration. +// +raw_ostream &GenWriter::printType(raw_ostream &Out, Type *Ty, + bool isSigned, const std::string &NameSoFar, + bool IgnoreName, const AttrListPtr &PAL) { + if (Ty->isPrimitiveType() || Ty->isIntegerTy() || Ty->isVectorTy()) { + printSimpleType(Out, Ty, isSigned, NameSoFar); + return Out; + } + + switch (Ty->getTypeID()) { + case Type::FunctionTyID: { + FunctionType *FTy = cast(Ty); + std::string tstr; + raw_string_ostream FunctionInnards(tstr); + FunctionInnards << " (" << NameSoFar << ") ("; + unsigned Idx = 1; + for (FunctionType::param_iterator I = FTy->param_begin(), + E = FTy->param_end(); I != E; ++I) { + Type *ArgTy = *I; + if (PAL.paramHasAttr(Idx, Attribute::ByVal)) { + assert(ArgTy->isPointerTy()); + ArgTy = cast(ArgTy)->getElementType(); + } + if (I != FTy->param_begin()) + FunctionInnards << ", "; + printType(FunctionInnards, ArgTy, + /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt), ""); + ++Idx; + } + if (FTy->isVarArg()) { + if (!FTy->getNumParams()) + FunctionInnards << " int"; //dummy argument for empty vaarg functs + FunctionInnards << ", ..."; + } else if (!FTy->getNumParams()) { + FunctionInnards << "void"; + } + FunctionInnards << ')'; + printType(Out, FTy->getReturnType(), + /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), FunctionInnards.str()); + return Out; + } + case Type::StructTyID: { + StructType *STy = cast(Ty); + + // Check to see if the type is named. + if (!IgnoreName) + return Out << getStructName(STy) << ' ' << NameSoFar; + + Out << NameSoFar + " {\n"; + unsigned Idx = 0; + for (StructType::element_iterator I = STy->element_begin(), + E = STy->element_end(); I != E; ++I) { + Out << " "; + printType(Out, *I, false, "field" + utostr(Idx++)); + Out << ";\n"; + } + Out << '}'; + if (STy->isPacked()) + Out << " __attribute__ ((packed))"; + return Out; + } + + case Type::PointerTyID: { + PointerType *PTy = cast(Ty); + std::string ptrName = "*" + NameSoFar; + + if (PTy->getElementType()->isArrayTy() || + PTy->getElementType()->isVectorTy()) + ptrName = "(" + ptrName + ")"; + + if (!PAL.isEmpty()) + // Must be a function ptr cast! + return printType(Out, PTy->getElementType(), false, ptrName, true, PAL); + return printType(Out, PTy->getElementType(), false, ptrName); + } + + case Type::ArrayTyID: { + ArrayType *ATy = cast(Ty); + unsigned NumElements = ATy->getNumElements(); + if (NumElements == 0) NumElements = 1; + // Arrays are wrapped in structs to allow them to have normal + // value semantics (avoiding the array "decay"). + Out << NameSoFar << " { "; + printType(Out, ATy->getElementType(), false, + "array[" + utostr(NumElements) + "]"); + return Out << "; }"; + } + + default: + llvm_unreachable("Unhandled case in getTypeProps!"); + } + + return Out; +} + +void GenWriter::printConstantArray(ConstantArray *CPA, bool Static) { + + // As a special case, print the array as a string if it is an array of + // ubytes or an array of sbytes with positive values. + // + Type *ETy = CPA->getType()->getElementType(); + bool isString = (ETy == Type::getInt8Ty(CPA->getContext()) || + ETy == Type::getInt8Ty(CPA->getContext())); + + // Make sure the last character is a null char, as automatically added by C + if (isString && (CPA->getNumOperands() == 0 || + !cast(*(CPA->op_end()-1))->isNullValue())) + isString = false; + + if (isString) { + Out << '\"'; + // Keep track of whether the last number was a hexadecimal escape. + bool LastWasHex = false; + + // Do not include the last character, which we know is null + for (unsigned i = 0, e = CPA->getNumOperands()-1; i != e; ++i) { + unsigned char C = cast(CPA->getOperand(i))->getZExtValue(); + + // Print it out literally if it is a printable character. The only thing + // to be careful about is when the last letter output was a hex escape + // code, in which case we have to be careful not to print out hex digits + // explicitly (the C compiler thinks it is a continuation of the previous + // character, sheesh...) + // + if (isprint(C) && (!LastWasHex || !isxdigit(C))) { + LastWasHex = false; + if (C == '"' || C == '\\') + Out << "\\" << (char)C; + else + Out << (char)C; + } else { + LastWasHex = false; + switch (C) { + case '\n': Out << "\\n"; break; + case '\t': Out << "\\t"; break; + case '\r': Out << "\\r"; break; + case '\v': Out << "\\v"; break; + case '\a': Out << "\\a"; break; + case '\"': Out << "\\\""; break; + case '\'': Out << "\\\'"; break; + default: + Out << "\\x"; + Out << (char)(( C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A')); + Out << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A')); + LastWasHex = true; + break; + } + } + } + Out << '\"'; + } else { + Out << '{'; + if (CPA->getNumOperands()) { + Out << ' '; + printConstant(cast(CPA->getOperand(0)), Static); + for (unsigned i = 1, e = CPA->getNumOperands(); i != e; ++i) { + Out << ", "; + printConstant(cast(CPA->getOperand(i)), Static); + } + } + Out << " }"; + } +} + +void GenWriter::printConstantVector(ConstantVector *CP, bool Static) { + Out << '{'; + if (CP->getNumOperands()) { + Out << ' '; + printConstant(cast(CP->getOperand(0)), Static); + for (unsigned i = 1, e = CP->getNumOperands(); i != e; ++i) { + Out << ", "; + printConstant(cast(CP->getOperand(i)), Static); + } + } + Out << " }"; +} + +// isFPCSafeToPrint - Returns true if we may assume that CFP may be written out +// textually as a double (rather than as a reference to a stack-allocated +// variable). We decide this by converting CFP to a string and back into a +// double, and then checking whether the conversion results in a bit-equal +// double to the original value of CFP. This depends on us and the target C +// compiler agreeing on the conversion process (which is pretty likely since we +// only deal in IEEE FP). +// +static bool isFPCSafeToPrint(const ConstantFP *CFP) { + bool ignored; + // Do long doubles in hex for now. + if (CFP->getType() != Type::getFloatTy(CFP->getContext()) && + CFP->getType() != Type::getDoubleTy(CFP->getContext())) + return false; + APFloat APF = APFloat(CFP->getValueAPF()); // copy + if (CFP->getType() == Type::getFloatTy(CFP->getContext())) + APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored); +#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A + char Buffer[100]; + sprintf(Buffer, "%a", APF.convertToDouble()); + if (!strncmp(Buffer, "0x", 2) || + !strncmp(Buffer, "-0x", 3) || + !strncmp(Buffer, "+0x", 3)) + return APF.bitwiseIsEqual(APFloat(atof(Buffer))); + return false; +#else + std::string StrVal = ftostr(APF); + + while (StrVal[0] == ' ') + StrVal.erase(StrVal.begin()); + + // Check to make sure that the stringized number is not some string like "Inf" + // or NaN. Check that the string matches the "[-+]?[0-9]" regex. + if ((StrVal[0] >= '0' && StrVal[0] <= '9') || + ((StrVal[0] == '-' || StrVal[0] == '+') && + (StrVal[1] >= '0' && StrVal[1] <= '9'))) + // Reparse stringized version! + return APF.bitwiseIsEqual(APFloat(atof(StrVal.c_str()))); + return false; +#endif +} + +/// Print out the casting for a cast operation. This does the double casting +/// necessary for conversion to the destination type, if necessary. +/// @brief Print a cast +void GenWriter::printCast(unsigned opc, Type *SrcTy, Type *DstTy) { + // Print the destination type cast + switch (opc) { + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::IntToPtr: + case Instruction::Trunc: + case Instruction::BitCast: + case Instruction::FPExt: + case Instruction::FPTrunc: // For these the DstTy sign doesn't matter + Out << '('; + printType(Out, DstTy); + Out << ')'; + break; + case Instruction::ZExt: + case Instruction::PtrToInt: + case Instruction::FPToUI: // For these, make sure we get an unsigned dest + Out << '('; + printSimpleType(Out, DstTy, false); + Out << ')'; + break; + case Instruction::SExt: + case Instruction::FPToSI: // For these, make sure we get a signed dest + Out << '('; + printSimpleType(Out, DstTy, true); + Out << ')'; + break; + default: + llvm_unreachable("Invalid cast opcode"); + } + + // Print the source type cast + switch (opc) { + case Instruction::UIToFP: + case Instruction::ZExt: + Out << '('; + printSimpleType(Out, SrcTy, false); + Out << ')'; + break; + case Instruction::SIToFP: + case Instruction::SExt: + Out << '('; + printSimpleType(Out, SrcTy, true); + Out << ')'; + break; + case Instruction::IntToPtr: + case Instruction::PtrToInt: + // Avoid "cast to pointer from integer of different size" warnings + Out << "(unsigned long)"; + break; + case Instruction::Trunc: + case Instruction::BitCast: + case Instruction::FPExt: + case Instruction::FPTrunc: + case Instruction::FPToSI: + case Instruction::FPToUI: + break; // These don't need a source cast. + default: + llvm_unreachable("Invalid cast opcode"); + break; + } +} + +// printConstant - The LLVM Constant to C Constant converter. +void GenWriter::printConstant(Constant *CPV, bool Static) { + if (const ConstantExpr *CE = dyn_cast(CPV)) { + switch (CE->getOpcode()) { + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::PtrToInt: + case Instruction::IntToPtr: + case Instruction::BitCast: + Out << "("; + printCast(CE->getOpcode(), CE->getOperand(0)->getType(), CE->getType()); + if (CE->getOpcode() == Instruction::SExt && + CE->getOperand(0)->getType() == Type::getInt1Ty(CPV->getContext())) { + // Make sure we really sext from bool here by subtracting from 0 + Out << "0-"; + } + printConstant(CE->getOperand(0), Static); + if (CE->getType() == Type::getInt1Ty(CPV->getContext()) && + (CE->getOpcode() == Instruction::Trunc || + CE->getOpcode() == Instruction::FPToUI || + CE->getOpcode() == Instruction::FPToSI || + CE->getOpcode() == Instruction::PtrToInt)) { + // Make sure we really truncate to bool here by anding with 1 + Out << "&1u"; + } + Out << ')'; + return; + + case Instruction::GetElementPtr: + Out << "("; + printGEPExpression(CE->getOperand(0), gep_type_begin(CPV), + gep_type_end(CPV), Static); + Out << ")"; + return; + case Instruction::Select: + Out << '('; + printConstant(CE->getOperand(0), Static); + Out << '?'; + printConstant(CE->getOperand(1), Static); + Out << ':'; + printConstant(CE->getOperand(2), Static); + Out << ')'; + return; + case Instruction::Add: + case Instruction::FAdd: + case Instruction::Sub: + case Instruction::FSub: + case Instruction::Mul: + case Instruction::FMul: + case Instruction::SDiv: + case Instruction::UDiv: + case Instruction::FDiv: + case Instruction::URem: + case Instruction::SRem: + case Instruction::FRem: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + case Instruction::ICmp: + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + { + Out << '('; + bool NeedsClosingParens = printConstExprCast(CE, Static); + printConstantWithCast(CE->getOperand(0), CE->getOpcode()); + switch (CE->getOpcode()) { + case Instruction::Add: + case Instruction::FAdd: Out << " + "; break; + case Instruction::Sub: + case Instruction::FSub: Out << " - "; break; + case Instruction::Mul: + case Instruction::FMul: Out << " * "; break; + case Instruction::URem: + case Instruction::SRem: + case Instruction::FRem: Out << " % "; break; + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::FDiv: Out << " / "; break; + case Instruction::And: Out << " & "; break; + case Instruction::Or: Out << " | "; break; + case Instruction::Xor: Out << " ^ "; break; + case Instruction::Shl: Out << " << "; break; + case Instruction::LShr: + case Instruction::AShr: Out << " >> "; break; + case Instruction::ICmp: + switch (CE->getPredicate()) { + case ICmpInst::ICMP_EQ: Out << " == "; break; + case ICmpInst::ICMP_NE: Out << " != "; break; + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_ULT: Out << " < "; break; + case ICmpInst::ICMP_SLE: + case ICmpInst::ICMP_ULE: Out << " <= "; break; + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_UGT: Out << " > "; break; + case ICmpInst::ICMP_SGE: + case ICmpInst::ICMP_UGE: Out << " >= "; break; + default: llvm_unreachable("Illegal ICmp predicate"); + } + break; + default: llvm_unreachable("Illegal opcode here!"); + } + printConstantWithCast(CE->getOperand(1), CE->getOpcode()); + if (NeedsClosingParens) + Out << "))"; + Out << ')'; + return; + } + case Instruction::FCmp: { + Out << '('; + bool NeedsClosingParens = printConstExprCast(CE, Static); + if (CE->getPredicate() == FCmpInst::FCMP_FALSE) + Out << "0"; + else if (CE->getPredicate() == FCmpInst::FCMP_TRUE) + Out << "1"; + else { + const char* op = 0; + switch (CE->getPredicate()) { + default: llvm_unreachable("Illegal FCmp predicate"); + case FCmpInst::FCMP_ORD: op = "ord"; break; + case FCmpInst::FCMP_UNO: op = "uno"; break; + case FCmpInst::FCMP_UEQ: op = "ueq"; break; + case FCmpInst::FCMP_UNE: op = "une"; break; + case FCmpInst::FCMP_ULT: op = "ult"; break; + case FCmpInst::FCMP_ULE: op = "ule"; break; + case FCmpInst::FCMP_UGT: op = "ugt"; break; + case FCmpInst::FCMP_UGE: op = "uge"; break; + case FCmpInst::FCMP_OEQ: op = "oeq"; break; + case FCmpInst::FCMP_ONE: op = "one"; break; + case FCmpInst::FCMP_OLT: op = "olt"; break; + case FCmpInst::FCMP_OLE: op = "ole"; break; + case FCmpInst::FCMP_OGT: op = "ogt"; break; + case FCmpInst::FCMP_OGE: op = "oge"; break; + } + Out << "llvm_fcmp_" << op << "("; + printConstantWithCast(CE->getOperand(0), CE->getOpcode()); + Out << ", "; + printConstantWithCast(CE->getOperand(1), CE->getOpcode()); + Out << ")"; + } + if (NeedsClosingParens) + Out << "))"; + Out << ')'; + return; + } + default: +#ifndef NDEBUG + errs() << "GenWriter Error: Unhandled constant expression: " + << *CE << "\n"; +#endif + llvm_unreachable(0); + } + } else if (isa(CPV) && CPV->getType()->isSingleValueType()) { + Out << "(("; + printType(Out, CPV->getType()); // sign doesn't matter + Out << ")/*UNDEF*/"; + if (!CPV->getType()->isVectorTy()) { + Out << "0)"; + } else { + Out << "{})"; + } + return; + } + + if (ConstantInt *CI = dyn_cast(CPV)) { + Type* Ty = CI->getType(); + if (Ty == Type::getInt1Ty(CPV->getContext())) + Out << (CI->getZExtValue() ? '1' : '0'); + else if (Ty == Type::getInt32Ty(CPV->getContext())) + Out << CI->getZExtValue() << 'u'; + else if (Ty->getPrimitiveSizeInBits() > 32) + Out << CI->getZExtValue() << "ull"; + else { + Out << "(("; + printSimpleType(Out, Ty, false) << ')'; + if (CI->isMinValue(true)) + Out << CI->getZExtValue() << 'u'; + else + Out << CI->getSExtValue(); + Out << ')'; + } + return; + } + + switch (CPV->getType()->getTypeID()) { + case Type::FloatTyID: + case Type::DoubleTyID: + case Type::X86_FP80TyID: + case Type::PPC_FP128TyID: + case Type::FP128TyID: { + ConstantFP *FPC = cast(CPV); + std::map::iterator I = FPConstantMap.find(FPC); + if (I != FPConstantMap.end()) { + // Because of FP precision problems we must load from a stack allocated + // value that holds the value in hex. + Out << "(*(" << (FPC->getType() == Type::getFloatTy(CPV->getContext()) ? + "float" : + FPC->getType() == Type::getDoubleTy(CPV->getContext()) ? + "double" : + "long double") + << "*)&FPConstant" << I->second << ')'; + } else { + double V; + if (FPC->getType() == Type::getFloatTy(CPV->getContext())) + V = FPC->getValueAPF().convertToFloat(); + else if (FPC->getType() == Type::getDoubleTy(CPV->getContext())) + V = FPC->getValueAPF().convertToDouble(); + else { + // Long double. Convert the number to double, discarding precision. + // This is not awesome, but it at least makes the CBE output somewhat + // useful. + APFloat Tmp = FPC->getValueAPF(); + bool LosesInfo; + Tmp.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &LosesInfo); + V = Tmp.convertToDouble(); + } + + if (IsNAN(V)) { + // The value is NaN + + // FIXME the actual NaN bits should be emitted. + // The prefix for a quiet NaN is 0x7FF8. For a signalling NaN, + // it's 0x7ff4. + const unsigned long QuietNaN = 0x7ff8UL; + //const unsigned long SignalNaN = 0x7ff4UL; + + // We need to grab the first part of the FP # + char Buffer[100]; + + uint64_t ll = DoubleToBits(V); + sprintf(Buffer, "0x%llx", static_cast(ll)); + + std::string Num(&Buffer[0], &Buffer[6]); + unsigned long Val = strtoul(Num.c_str(), 0, 16); + + if (FPC->getType() == Type::getFloatTy(FPC->getContext())) + Out << "LLVM_NAN" << (Val == QuietNaN ? "" : "S") << "F(\"" + << Buffer << "\") /*nan*/ "; + else + Out << "LLVM_NAN" << (Val == QuietNaN ? "" : "S") << "(\"" + << Buffer << "\") /*nan*/ "; + } else if (IsInf(V)) { + // The value is Inf + if (V < 0) Out << '-'; + Out << "LLVM_INF" << + (FPC->getType() == Type::getFloatTy(FPC->getContext()) ? "F" : "") + << " /*inf*/ "; + } else { + std::string Num; +#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A + // Print out the constant as a floating point number. + char Buffer[100]; + sprintf(Buffer, "%a", V); + Num = Buffer; +#else + Num = ftostr(FPC->getValueAPF()); +#endif + Out << Num; + } + } + break; + } + + case Type::ArrayTyID: + // Use C99 compound expression literal initializer syntax. + if (!Static) { + Out << "("; + printType(Out, CPV->getType()); + Out << ")"; + } + Out << "{ "; // Arrays are wrapped in struct types. + if (ConstantArray *CA = dyn_cast(CPV)) { + printConstantArray(CA, Static); + } else { + assert(isa(CPV) || isa(CPV)); + ArrayType *AT = cast(CPV->getType()); + Out << '{'; + if (AT->getNumElements()) { + Out << ' '; + Constant *CZ = Constant::getNullValue(AT->getElementType()); + printConstant(CZ, Static); + for (unsigned i = 1, e = AT->getNumElements(); i != e; ++i) { + Out << ", "; + printConstant(CZ, Static); + } + } + Out << " }"; + } + Out << " }"; // Arrays are wrapped in struct types. + break; + + case Type::VectorTyID: + // Use C99 compound expression literal initializer syntax. + if (!Static) { + Out << "("; + printType(Out, CPV->getType()); + Out << ")"; + } + if (ConstantVector *CV = dyn_cast(CPV)) { + printConstantVector(CV, Static); + } else { + assert(isa(CPV) || isa(CPV)); + VectorType *VT = cast(CPV->getType()); + Out << "{ "; + Constant *CZ = Constant::getNullValue(VT->getElementType()); + printConstant(CZ, Static); + for (unsigned i = 1, e = VT->getNumElements(); i != e; ++i) { + Out << ", "; + printConstant(CZ, Static); + } + Out << " }"; + } + break; + + case Type::StructTyID: + // Use C99 compound expression literal initializer syntax. + if (!Static) { + Out << "("; + printType(Out, CPV->getType()); + Out << ")"; + } + if (isa(CPV) || isa(CPV)) { + StructType *ST = cast(CPV->getType()); + Out << '{'; + if (ST->getNumElements()) { + Out << ' '; + printConstant(Constant::getNullValue(ST->getElementType(0)), Static); + for (unsigned i = 1, e = ST->getNumElements(); i != e; ++i) { + Out << ", "; + printConstant(Constant::getNullValue(ST->getElementType(i)), Static); + } + } + Out << " }"; + } else { + Out << '{'; + if (CPV->getNumOperands()) { + Out << ' '; + printConstant(cast(CPV->getOperand(0)), Static); + for (unsigned i = 1, e = CPV->getNumOperands(); i != e; ++i) { + Out << ", "; + printConstant(cast(CPV->getOperand(i)), Static); + } + } + Out << " }"; + } + break; + + case Type::PointerTyID: + if (isa(CPV)) { + Out << "(("; + printType(Out, CPV->getType()); // sign doesn't matter + Out << ")/*NULL*/0)"; + break; + } else if (GlobalValue *GV = dyn_cast(CPV)) { + writeOperand(GV, Static); + break; + } + // FALL THROUGH + default: +#ifndef NDEBUG + errs() << "Unknown constant type: " << *CPV << "\n"; +#endif + llvm_unreachable(0); + } +} + +// Some constant expressions need to be casted back to the original types +// because their operands were casted to the expected type. This function takes +// care of detecting that case and printing the cast for the ConstantExpr. +bool GenWriter::printConstExprCast(const ConstantExpr* CE, bool Static) { + bool NeedsExplicitCast = false; + Type *Ty = CE->getOperand(0)->getType(); + bool TypeIsSigned = false; + switch (CE->getOpcode()) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + // We need to cast integer arithmetic so that it is always performed + // as unsigned, to avoid undefined behavior on overflow. + case Instruction::LShr: + case Instruction::URem: + case Instruction::UDiv: NeedsExplicitCast = true; break; + case Instruction::AShr: + case Instruction::SRem: + case Instruction::SDiv: NeedsExplicitCast = true; TypeIsSigned = true; break; + case Instruction::SExt: + Ty = CE->getType(); + NeedsExplicitCast = true; + TypeIsSigned = true; + break; + case Instruction::ZExt: + case Instruction::Trunc: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::PtrToInt: + case Instruction::IntToPtr: + case Instruction::BitCast: + Ty = CE->getType(); + NeedsExplicitCast = true; + break; + default: break; + } + if (NeedsExplicitCast) { + Out << "(("; + if (Ty->isIntegerTy() && Ty != Type::getInt1Ty(Ty->getContext())) + printSimpleType(Out, Ty, TypeIsSigned); + else + printType(Out, Ty); // not integer, sign doesn't matter + Out << ")("; + } + return NeedsExplicitCast; +} + +// Print a constant assuming that it is the operand for a given Opcode. The +// opcodes that care about sign need to cast their operands to the expected +// type before the operation proceeds. This function does the casting. +void GenWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) { + + // Extract the operand's type, we'll need it. + Type* OpTy = CPV->getType(); + + // Indicate whether to do the cast or not. + bool shouldCast = false; + bool typeIsSigned = false; + + // Based on the Opcode for which this Constant is being written, determine + // the new type to which the operand should be casted by setting the value + // of OpTy. If we change OpTy, also set shouldCast to true so it gets + // casted below. + switch (Opcode) { + default: + // for most instructions, it doesn't matter + break; + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + // We need to cast integer arithmetic so that it is always performed + // as unsigned, to avoid undefined behavior on overflow. + case Instruction::LShr: + case Instruction::UDiv: + case Instruction::URem: + shouldCast = true; + break; + case Instruction::AShr: + case Instruction::SDiv: + case Instruction::SRem: + shouldCast = true; + typeIsSigned = true; + break; + } + + // Write out the casted constant if we should, otherwise just write the + // operand. + if (shouldCast) { + Out << "(("; + printSimpleType(Out, OpTy, typeIsSigned); + Out << ")"; + printConstant(CPV, false); + Out << ")"; + } else + printConstant(CPV, false); +} + +std::string GenWriter::GetValueName(const Value *Operand) { + + // Resolve potential alias. + if (const GlobalAlias *GA = dyn_cast(Operand)) { + if (const Value *V = GA->resolveAliasedGlobal(false)) + Operand = V; + } + + // Mangle globals with the standard mangler interface for LLC compatibility. + if (const GlobalValue *GV = dyn_cast(Operand)) { + SmallString<128> Str; + Mang->getNameWithPrefix(Str, GV, false); + return CBEMangle(Str.str().str()); + } + + std::string Name = Operand->getName(); + + if (Name.empty()) { // Assign unique names to local temporaries. + unsigned &No = AnonValueNumbers[Operand]; + if (No == 0) + No = ++NextAnonValueNumber; + Name = "tmp__" + utostr(No); + } + + std::string VarName; + VarName.reserve(Name.capacity()); + + for (std::string::iterator I = Name.begin(), E = Name.end(); + I != E; ++I) { + char ch = *I; + + if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || ch == '_')) { + char buffer[5]; + sprintf(buffer, "_%x_", ch); + VarName += buffer; + } else + VarName += ch; + } + + return "llvm_cbe_" + VarName; +} + +/// writeInstComputationInline - Emit the computation for the specified +/// instruction inline, with no destination provided. +void GenWriter::writeInstComputationInline(Instruction &I) { + // We can't currently support integer types other than 1, 8, 16, 32, 64. + // Validate this. + Type *Ty = I.getType(); + if (Ty->isIntegerTy() && (Ty!=Type::getInt1Ty(I.getContext()) && + Ty!=Type::getInt8Ty(I.getContext()) && + Ty!=Type::getInt16Ty(I.getContext()) && + Ty!=Type::getInt32Ty(I.getContext()) && + Ty!=Type::getInt64Ty(I.getContext()))) { + report_fatal_error("The C backend does not currently support integer " + "types of widths other than 1, 8, 16, 32, 64.\n" + "This is being tracked as PR 4158."); + } + + // If this is a non-trivial bool computation, make sure to truncate down to + // a 1 bit value. This is important because we want "add i1 x, y" to return + // "0" when x and y are true, not "2" for example. + bool NeedBoolTrunc = false; + if (I.getType() == Type::getInt1Ty(I.getContext()) && + !isa(I) && !isa(I)) + NeedBoolTrunc = true; + + if (NeedBoolTrunc) + Out << "(("; + + visit(I); + + if (NeedBoolTrunc) + Out << ")&1)"; +} + + +void GenWriter::writeOperandInternal(Value *Operand, bool Static) { + if (Instruction *I = dyn_cast(Operand)) + // Should we inline this instruction to build a tree? + if (isInlinableInst(*I) && !isDirectAlloca(I)) { + Out << '('; + writeInstComputationInline(*I); + Out << ')'; + return; + } + + Constant* CPV = dyn_cast(Operand); + + if (CPV && !isa(CPV)) + printConstant(CPV, Static); + else + Out << GetValueName(Operand); +} + +void GenWriter::writeOperand(Value *Operand, bool Static) { + bool isAddressImplicit = isAddressExposed(Operand); + if (isAddressImplicit) + Out << "(&"; // Global variables are referenced as their addresses by llvm + + writeOperandInternal(Operand, Static); + + if (isAddressImplicit) + Out << ')'; +} + +// Some instructions need to have their result value casted back to the +// original types because their operands were casted to the expected type. +// This function takes care of detecting that case and printing the cast +// for the Instruction. +bool GenWriter::writeInstructionCast(const Instruction &I) { + Type *Ty = I.getOperand(0)->getType(); + switch (I.getOpcode()) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + // We need to cast integer arithmetic so that it is always performed + // as unsigned, to avoid undefined behavior on overflow. + case Instruction::LShr: + case Instruction::URem: + case Instruction::UDiv: + Out << "(("; + printSimpleType(Out, Ty, false); + Out << ")("; + return true; + case Instruction::AShr: + case Instruction::SRem: + case Instruction::SDiv: + Out << "(("; + printSimpleType(Out, Ty, true); + Out << ")("; + return true; + default: break; + } + return false; +} + +// Write the operand with a cast to another type based on the Opcode being used. +// This will be used in cases where an instruction has specific type +// requirements (usually signedness) for its operands. +void GenWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) { + + // Extract the operand's type, we'll need it. + Type* OpTy = Operand->getType(); + + // Indicate whether to do the cast or not. + bool shouldCast = false; + + // Indicate whether the cast should be to a signed type or not. + bool castIsSigned = false; + + // Based on the Opcode for which this Operand is being written, determine + // the new type to which the operand should be casted by setting the value + // of OpTy. If we change OpTy, also set shouldCast to true. + switch (Opcode) { + default: + // for most instructions, it doesn't matter + break; + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + // We need to cast integer arithmetic so that it is always performed + // as unsigned, to avoid undefined behavior on overflow. + case Instruction::LShr: + case Instruction::UDiv: + case Instruction::URem: // Cast to unsigned first + shouldCast = true; + castIsSigned = false; + break; + case Instruction::GetElementPtr: + case Instruction::AShr: + case Instruction::SDiv: + case Instruction::SRem: // Cast to signed first + shouldCast = true; + castIsSigned = true; + break; + } + + // Write out the casted operand if we should, otherwise just write the + // operand. + if (shouldCast) { + Out << "(("; + printSimpleType(Out, OpTy, castIsSigned); + Out << ")"; + writeOperand(Operand); + Out << ")"; + } else + writeOperand(Operand); +} + +// Write the operand with a cast to another type based on the icmp predicate +// being used. +void GenWriter::writeOperandWithCast(Value* Operand, const ICmpInst &Cmp) { + // This has to do a cast to ensure the operand has the right signedness. + // Also, if the operand is a pointer, we make sure to cast to an integer when + // doing the comparison both for signedness and so that the C compiler doesn't + // optimize things like "p < NULL" to false (p may contain an integer value + // f.e.). + bool shouldCast = Cmp.isRelational(); + + // Write out the casted operand if we should, otherwise just write the + // operand. + if (!shouldCast) { + writeOperand(Operand); + return; + } + + // Should this be a signed comparison? If so, convert to signed. + bool castIsSigned = Cmp.isSigned(); + + // If the operand was a pointer, convert to a large integer type. + Type* OpTy = Operand->getType(); + if (OpTy->isPointerTy()) + OpTy = TD->getIntPtrType(Operand->getContext()); + + Out << "(("; + printSimpleType(Out, OpTy, castIsSigned); + Out << ")"; + writeOperand(Operand); + Out << ")"; +} + +// generateCompilerSpecificCode - This is where we add conditional compilation +// directives to cater to specific compilers as need be. +// +static void generateCompilerSpecificCode(formatted_raw_ostream& Out, + const TargetData *TD) { + // Alloca is hard to get, and we don't want to include stdlib.h here. + Out << "/* get a declaration for alloca */\n" + << "#if defined(__CYGWIN__) || defined(__MINGW32__)\n" + << "#define alloca(x) __builtin_alloca((x))\n" + << "#define _alloca(x) __builtin_alloca((x))\n" + << "#elif defined(__APPLE__)\n" + << "extern void *__builtin_alloca(unsigned long);\n" + << "#define alloca(x) __builtin_alloca(x)\n" + << "#define longjmp _longjmp\n" + << "#define setjmp _setjmp\n" + << "#elif defined(__sun__)\n" + << "#if defined(__sparcv9)\n" + << "extern void *__builtin_alloca(unsigned long);\n" + << "#else\n" + << "extern void *__builtin_alloca(unsigned int);\n" + << "#endif\n" + << "#define alloca(x) __builtin_alloca(x)\n" + << "#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__arm__)\n" + << "#define alloca(x) __builtin_alloca(x)\n" + << "#elif defined(_MSC_VER)\n" + << "#define inline _inline\n" + << "#define alloca(x) _alloca(x)\n" + << "#else\n" + << "#include \n" + << "#endif\n\n"; + + // We output GCC specific attributes to preserve 'linkonce'ness on globals. + // If we aren't being compiled with GCC, just drop these attributes. + Out << "#ifndef __GNUC__ /* Can only support \"linkonce\" vars with GCC */\n" + << "#define __attribute__(X)\n" + << "#endif\n\n"; + + // On Mac OS X, "external weak" is spelled "__attribute__((weak_import))". + Out << "#if defined(__GNUC__) && defined(__APPLE_CC__)\n" + << "#define __EXTERNAL_WEAK__ __attribute__((weak_import))\n" + << "#elif defined(__GNUC__)\n" + << "#define __EXTERNAL_WEAK__ __attribute__((weak))\n" + << "#else\n" + << "#define __EXTERNAL_WEAK__\n" + << "#endif\n\n"; + + // For now, turn off the weak linkage attribute on Mac OS X. (See above.) + Out << "#if defined(__GNUC__) && defined(__APPLE_CC__)\n" + << "#define __ATTRIBUTE_WEAK__\n" + << "#elif defined(__GNUC__)\n" + << "#define __ATTRIBUTE_WEAK__ __attribute__((weak))\n" + << "#else\n" + << "#define __ATTRIBUTE_WEAK__\n" + << "#endif\n\n"; + + // Add hidden visibility support. FIXME: APPLE_CC? + Out << "#if defined(__GNUC__)\n" + << "#define __HIDDEN__ __attribute__((visibility(\"hidden\")))\n" + << "#endif\n\n"; + + // Define NaN and Inf as GCC builtins if using GCC, as 0 otherwise + // From the GCC documentation: + // + // double __builtin_nan (const char *str) + // + // This is an implementation of the ISO C99 function nan. + // + // Since ISO C99 defines this function in terms of strtod, which we do + // not implement, a description of the parsing is in order. The string is + // parsed as by strtol; that is, the base is recognized by leading 0 or + // 0x prefixes. The number parsed is placed in the significand such that + // the least significant bit of the number is at the least significant + // bit of the significand. The number is truncated to fit the significand + // field provided. The significand is forced to be a quiet NaN. + // + // This function, if given a string literal, is evaluated early enough + // that it is considered a compile-time constant. + // + // float __builtin_nanf (const char *str) + // + // Similar to __builtin_nan, except the return type is float. + // + // double __builtin_inf (void) + // + // Similar to __builtin_huge_val, except a warning is generated if the + // target floating-point format does not support infinities. This + // function is suitable for implementing the ISO C99 macro INFINITY. + // + // float __builtin_inff (void) + // + // Similar to __builtin_inf, except the return type is float. + Out << "#ifdef __GNUC__\n" + << "#define LLVM_NAN(NanStr) __builtin_nan(NanStr) /* Double */\n" + << "#define LLVM_NANF(NanStr) __builtin_nanf(NanStr) /* Float */\n" + << "#define LLVM_NANS(NanStr) __builtin_nans(NanStr) /* Double */\n" + << "#define LLVM_NANSF(NanStr) __builtin_nansf(NanStr) /* Float */\n" + << "#define LLVM_INF __builtin_inf() /* Double */\n" + << "#define LLVM_INFF __builtin_inff() /* Float */\n" + << "#define LLVM_PREFETCH(addr,rw,locality) " + "__builtin_prefetch(addr,rw,locality)\n" + << "#define __ATTRIBUTE_CTOR__ __attribute__((constructor))\n" + << "#define __ATTRIBUTE_DTOR__ __attribute__((destructor))\n" + << "#define LLVM_ASM __asm__\n" + << "#else\n" + << "#define LLVM_NAN(NanStr) ((double)0.0) /* Double */\n" + << "#define LLVM_NANF(NanStr) 0.0F /* Float */\n" + << "#define LLVM_NANS(NanStr) ((double)0.0) /* Double */\n" + << "#define LLVM_NANSF(NanStr) 0.0F /* Float */\n" + << "#define LLVM_INF ((double)0.0) /* Double */\n" + << "#define LLVM_INFF 0.0F /* Float */\n" + << "#define LLVM_PREFETCH(addr,rw,locality) /* PREFETCH */\n" + << "#define __ATTRIBUTE_CTOR__\n" + << "#define __ATTRIBUTE_DTOR__\n" + << "#define LLVM_ASM(X)\n" + << "#endif\n\n"; + + Out << "#if __GNUC__ < 4 /* Old GCC's, or compilers not GCC */ \n" + << "#define __builtin_stack_save() 0 /* not implemented */\n" + << "#define __builtin_stack_restore(X) /* noop */\n" + << "#endif\n\n"; + + // Output typedefs for 128-bit integers. If these are needed with a + // 32-bit target or with a C compiler that doesn't support mode(TI), + // more drastic measures will be needed. + Out << "#if __GNUC__ && __LP64__ /* 128-bit integer types */\n" + << "typedef int __attribute__((mode(TI))) llvmInt128;\n" + << "typedef unsigned __attribute__((mode(TI))) llvmUInt128;\n" + << "#endif\n\n"; + + // Output target-specific code that should be inserted into main. + Out << "#define CODE_FOR_MAIN() /* Any target-specific code for main()*/\n"; +} + +/// FindStaticTors - Given a static ctor/dtor list, unpack its contents into +/// the StaticTors set. +static void FindStaticTors(GlobalVariable *GV, std::set &StaticTors){ + ConstantArray *InitList = dyn_cast(GV->getInitializer()); + if (!InitList) return; + + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) + if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){ + if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. + + if (CS->getOperand(1)->isNullValue()) + return; // Found a null terminator, exit printing. + Constant *FP = CS->getOperand(1); + if (ConstantExpr *CE = dyn_cast(FP)) + if (CE->isCast()) + FP = CE->getOperand(0); + if (Function *F = dyn_cast(FP)) + StaticTors.insert(F); + } +} + +enum SpecialGlobalClass { + NotSpecial = 0, + GlobalCtors, GlobalDtors, + NotPrinted +}; + +/// getGlobalVariableClass - If this is a global that is specially recognized +/// by LLVM, return a code that indicates how we should handle it. +static SpecialGlobalClass getGlobalVariableClass(const GlobalVariable *GV) { + // If this is a global ctors/dtors list, handle it now. + if (GV->hasAppendingLinkage() && GV->use_empty()) { + if (GV->getName() == "llvm.global_ctors") + return GlobalCtors; + else if (GV->getName() == "llvm.global_dtors") + return GlobalDtors; + } + + // Otherwise, if it is other metadata, don't print it. This catches things + // like debug information. + if (GV->getSection() == "llvm.metadata") + return NotPrinted; + + return NotSpecial; +} + +// PrintEscapedString - Print each character of the specified string, escaping +// it if it is not printable or if it is an escape char. +static void PrintEscapedString(const char *Str, unsigned Length, + raw_ostream &Out) { + for (unsigned i = 0; i != Length; ++i) { + unsigned char C = Str[i]; + if (isprint(C) && C != '\\' && C != '"') + Out << C; + else if (C == '\\') + Out << "\\\\"; + else if (C == '\"') + Out << "\\\""; + else if (C == '\t') + Out << "\\t"; + else + Out << "\\x" << hexdigit(C >> 4) << hexdigit(C & 0x0F); + } +} + +// PrintEscapedString - Print each character of the specified string, escaping +// it if it is not printable or if it is an escape char. +static void PrintEscapedString(const std::string &Str, raw_ostream &Out) { + PrintEscapedString(Str.c_str(), Str.size(), Out); +} + +bool GenWriter::doInitialization(Module &M) { + FunctionPass::doInitialization(M); + + // Initialize + TheModule = &M; + + TD = new TargetData(&M); + IL = new IntrinsicLowering(*TD); + IL->AddPrototypes(M); + +#if 0 + std::string Triple = TheModule->getTargetTriple(); + if (Triple.empty()) + Triple = llvm::sys::getHostTriple(); + + std::string E; + if (const Target *Match = TargetRegistry::lookupTarget(Triple, E)) + TAsm = Match->createMCAsmInfo(Triple); +#endif + TAsm = new CBEMCAsmInfo(); + MRI = new MCRegisterInfo(); + TCtx = new MCContext(*TAsm, *MRI, NULL); + Mang = new Mangler(*TCtx, *TD); + + // Keep track of which functions are static ctors/dtors so they can have + // an attribute added to their prototypes. + std::set StaticCtors, StaticDtors; + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + switch (getGlobalVariableClass(I)) { + default: break; + case GlobalCtors: + FindStaticTors(I, StaticCtors); + break; + case GlobalDtors: + FindStaticTors(I, StaticDtors); + break; + } + } + + // get declaration for alloca + Out << "/* Provide Declarations */\n"; + Out << "#include \n"; // Varargs support + Out << "#include \n"; // Unwind support + Out << "#include \n"; // With overflow intrinsics support. + generateCompilerSpecificCode(Out, TD); + + // Provide a definition for `bool' if not compiling with a C++ compiler. + Out << "\n" + << "#ifndef __cplusplus\ntypedef unsigned char bool;\n#endif\n" + + << "\n\n/* Support for floating point constants */\n" + << "typedef unsigned long long ConstantDoubleTy;\n" + << "typedef unsigned int ConstantFloatTy;\n" + << "typedef struct { unsigned long long f1; unsigned short f2; " + "unsigned short pad[3]; } ConstantFP80Ty;\n" + // This is used for both kinds of 128-bit long double; meaning differs. + << "typedef struct { unsigned long long f1; unsigned long long f2; }" + " ConstantFP128Ty;\n" + << "\n\n/* Global Declarations */\n"; + + // First output all the declarations for the program, because C requires + // Functions & globals to be declared before they are used. + // + if (!M.getModuleInlineAsm().empty()) { + Out << "/* Module asm statements */\n" + << "asm("; + + // Split the string into lines, to make it easier to read the .ll file. + std::string Asm = M.getModuleInlineAsm(); + size_t CurPos = 0; + size_t NewLine = Asm.find_first_of('\n', CurPos); + while (NewLine != std::string::npos) { + // We found a newline, print the portion of the asm string from the + // last newline up to this newline. + Out << "\""; + PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.begin()+NewLine), + Out); + Out << "\\n\"\n"; + CurPos = NewLine+1; + NewLine = Asm.find_first_of('\n', CurPos); + } + Out << "\""; + PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.end()), Out); + Out << "\");\n" + << "/* End Module asm statements */\n"; + } + + // Loop over the symbol table, emitting all named constants. + printModuleTypes(); + + // Global variable declarations... + if (!M.global_empty()) { + Out << "\n/* External Global Variable Declarations */\n"; + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + + if (I->hasExternalLinkage() || I->hasExternalWeakLinkage() || + I->hasCommonLinkage()) + Out << "extern "; + else if (I->hasDLLImportLinkage()) + Out << "__declspec(dllimport) "; + else + continue; // Internal Global + + // Thread Local Storage + if (I->isThreadLocal()) + Out << "__thread "; + + printType(Out, I->getType()->getElementType(), false, GetValueName(I)); + + if (I->hasExternalWeakLinkage()) + Out << " __EXTERNAL_WEAK__"; + Out << ";\n"; + } + } + + // Function declarations + Out << "\n/* Function Declarations */\n"; + Out << "double fmod(double, double);\n"; // Support for FP rem + Out << "float fmodf(float, float);\n"; + Out << "long double fmodl(long double, long double);\n"; + + // Store the intrinsics which will be declared/defined below. + SmallVector intrinsicsToDefine; + + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + // Don't print declarations for intrinsic functions. + // Store the used intrinsics, which need to be explicitly defined. + if (I->isIntrinsic()) { + switch (I->getIntrinsicID()) { + default: + break; + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + intrinsicsToDefine.push_back(I); + break; + } + continue; + } + + if (I->getName() == "setjmp" || + I->getName() == "longjmp" || I->getName() == "_setjmp") + continue; + + if (I->hasExternalWeakLinkage()) + Out << "extern "; + printFunctionSignature(I, true); + if (I->hasWeakLinkage() || I->hasLinkOnceLinkage()) + Out << " __ATTRIBUTE_WEAK__"; + if (I->hasExternalWeakLinkage()) + Out << " __EXTERNAL_WEAK__"; + if (StaticCtors.count(I)) + Out << " __ATTRIBUTE_CTOR__"; + if (StaticDtors.count(I)) + Out << " __ATTRIBUTE_DTOR__"; + if (I->hasHiddenVisibility()) + Out << " __HIDDEN__"; + + if (I->hasName() && I->getName()[0] == 1) + Out << " LLVM_ASM(\"" << I->getName().substr(1) << "\")"; + + Out << ";\n"; + } + + // Output the global variable declarations + if (!M.global_empty()) { + Out << "\n\n/* Global Variable Declarations */\n"; + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + if (!I->isDeclaration()) { + // Ignore special globals, such as debug info. + if (getGlobalVariableClass(I)) + continue; + + if (I->hasLocalLinkage()) + Out << "static "; + else + Out << "extern "; + + // Thread Local Storage + if (I->isThreadLocal()) + Out << "__thread "; + + printType(Out, I->getType()->getElementType(), false, + GetValueName(I)); + + if (I->hasLinkOnceLinkage()) + Out << " __attribute__((common))"; + else if (I->hasCommonLinkage()) // FIXME is this right? + Out << " __ATTRIBUTE_WEAK__"; + else if (I->hasWeakLinkage()) + Out << " __ATTRIBUTE_WEAK__"; + else if (I->hasExternalWeakLinkage()) + Out << " __EXTERNAL_WEAK__"; + if (I->hasHiddenVisibility()) + Out << " __HIDDEN__"; + Out << ";\n"; + } + } + + // Output the global variable definitions and contents... + if (!M.global_empty()) { + Out << "\n\n/* Global Variable Definitions and Initialization */\n"; + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + if (!I->isDeclaration()) { + // Ignore special globals, such as debug info. + if (getGlobalVariableClass(I)) + continue; + + if (I->hasLocalLinkage()) + Out << "static "; + else if (I->hasDLLImportLinkage()) + Out << "__declspec(dllimport) "; + else if (I->hasDLLExportLinkage()) + Out << "__declspec(dllexport) "; + + // Thread Local Storage + if (I->isThreadLocal()) + Out << "__thread "; + + printType(Out, I->getType()->getElementType(), false, + GetValueName(I)); + if (I->hasLinkOnceLinkage()) + Out << " __attribute__((common))"; + else if (I->hasWeakLinkage()) + Out << " __ATTRIBUTE_WEAK__"; + else if (I->hasCommonLinkage()) + Out << " __ATTRIBUTE_WEAK__"; + + if (I->hasHiddenVisibility()) + Out << " __HIDDEN__"; + + // If the initializer is not null, emit the initializer. If it is null, + // we try to avoid emitting large amounts of zeros. The problem with + // this, however, occurs when the variable has weak linkage. In this + // case, the assembler will complain about the variable being both weak + // and common, so we disable this optimization. + // FIXME common linkage should avoid this problem. + if (!I->getInitializer()->isNullValue()) { + Out << " = " ; + writeOperand(I->getInitializer(), true); + } else if (I->hasWeakLinkage()) { + // We have to specify an initializer, but it doesn't have to be + // complete. If the value is an aggregate, print out { 0 }, and let + // the compiler figure out the rest of the zeros. + Out << " = " ; + if (I->getInitializer()->getType()->isStructTy() || + I->getInitializer()->getType()->isVectorTy()) { + Out << "{ 0 }"; + } else if (I->getInitializer()->getType()->isArrayTy()) { + // As with structs and vectors, but with an extra set of braces + // because arrays are wrapped in structs. + Out << "{ { 0 } }"; + } else { + // Just print it out normally. + writeOperand(I->getInitializer(), true); + } + } + Out << ";\n"; + } + } + + if (!M.empty()) + Out << "\n\n/* Function Bodies */\n"; + + // Emit some helper functions for dealing with FCMP instruction's + // predicates + Out << "static inline int llvm_fcmp_ord(double X, double Y) { "; + Out << "return X == X && Y == Y; }\n"; + Out << "static inline int llvm_fcmp_uno(double X, double Y) { "; + Out << "return X != X || Y != Y; }\n"; + Out << "static inline int llvm_fcmp_ueq(double X, double Y) { "; + Out << "return X == Y || llvm_fcmp_uno(X, Y); }\n"; + Out << "static inline int llvm_fcmp_une(double X, double Y) { "; + Out << "return X != Y; }\n"; + Out << "static inline int llvm_fcmp_ult(double X, double Y) { "; + Out << "return X < Y || llvm_fcmp_uno(X, Y); }\n"; + Out << "static inline int llvm_fcmp_ugt(double X, double Y) { "; + Out << "return X > Y || llvm_fcmp_uno(X, Y); }\n"; + Out << "static inline int llvm_fcmp_ule(double X, double Y) { "; + Out << "return X <= Y || llvm_fcmp_uno(X, Y); }\n"; + Out << "static inline int llvm_fcmp_uge(double X, double Y) { "; + Out << "return X >= Y || llvm_fcmp_uno(X, Y); }\n"; + Out << "static inline int llvm_fcmp_oeq(double X, double Y) { "; + Out << "return X == Y ; }\n"; + Out << "static inline int llvm_fcmp_one(double X, double Y) { "; + Out << "return X != Y && llvm_fcmp_ord(X, Y); }\n"; + Out << "static inline int llvm_fcmp_olt(double X, double Y) { "; + Out << "return X < Y ; }\n"; + Out << "static inline int llvm_fcmp_ogt(double X, double Y) { "; + Out << "return X > Y ; }\n"; + Out << "static inline int llvm_fcmp_ole(double X, double Y) { "; + Out << "return X <= Y ; }\n"; + Out << "static inline int llvm_fcmp_oge(double X, double Y) { "; + Out << "return X >= Y ; }\n"; + + // Emit definitions of the intrinsics. + for (SmallVector::const_iterator + I = intrinsicsToDefine.begin(), + E = intrinsicsToDefine.end(); I != E; ++I) { + printIntrinsicDefinition(**I, Out); + } + + return false; +} + + +/// Output all floating point constants that cannot be printed accurately... +void GenWriter::printFloatingPointConstants(Function &F) { + // Scan the module for floating point constants. If any FP constant is used + // in the function, we want to redirect it here so that we do not depend on + // the precision of the printed form, unless the printed form preserves + // precision. + // + for (constant_iterator I = constant_begin(&F), E = constant_end(&F); + I != E; ++I) + printFloatingPointConstants(*I); + + Out << '\n'; +} + +void GenWriter::printFloatingPointConstants(const Constant *C) { + // If this is a constant expression, recursively check for constant fp values. + if (const ConstantExpr *CE = dyn_cast(C)) { + for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) + printFloatingPointConstants(CE->getOperand(i)); + return; + } + + // Otherwise, check for a FP constant that we need to print. + const ConstantFP *FPC = dyn_cast(C); + if (FPC == 0 || + // Do not put in FPConstantMap if safe. + isFPCSafeToPrint(FPC) || + // Already printed this constant? + FPConstantMap.count(FPC)) + return; + + FPConstantMap[FPC] = FPCounter; // Number the FP constants + + if (FPC->getType() == Type::getDoubleTy(FPC->getContext())) { + double Val = FPC->getValueAPF().convertToDouble(); + uint64_t i = FPC->getValueAPF().bitcastToAPInt().getZExtValue(); + Out << "static const ConstantDoubleTy FPConstant" << FPCounter++ + << " = 0x" << utohexstr(i) + << "ULL; /* " << Val << " */\n"; + } else if (FPC->getType() == Type::getFloatTy(FPC->getContext())) { + float Val = FPC->getValueAPF().convertToFloat(); + uint32_t i = (uint32_t)FPC->getValueAPF().bitcastToAPInt(). + getZExtValue(); + Out << "static const ConstantFloatTy FPConstant" << FPCounter++ + << " = 0x" << utohexstr(i) + << "U; /* " << Val << " */\n"; + } else if (FPC->getType() == Type::getX86_FP80Ty(FPC->getContext())) { + // api needed to prevent premature destruction + APInt api = FPC->getValueAPF().bitcastToAPInt(); + const uint64_t *p = api.getRawData(); + Out << "static const ConstantFP80Ty FPConstant" << FPCounter++ + << " = { 0x" << utohexstr(p[0]) + << "ULL, 0x" << utohexstr((uint16_t)p[1]) << ",{0,0,0}" + << "}; /* Long double constant */\n"; + } else if (FPC->getType() == Type::getPPC_FP128Ty(FPC->getContext()) || + FPC->getType() == Type::getFP128Ty(FPC->getContext())) { + APInt api = FPC->getValueAPF().bitcastToAPInt(); + const uint64_t *p = api.getRawData(); + Out << "static const ConstantFP128Ty FPConstant" << FPCounter++ + << " = { 0x" + << utohexstr(p[0]) << ", 0x" << utohexstr(p[1]) + << "}; /* Long double constant */\n"; + + } else { + llvm_unreachable("Unknown float type!"); + } +} + + +/// printSymbolTable - Run through symbol table looking for type names. If a +/// type name is found, emit its declaration... +/// +void GenWriter::printModuleTypes() { + Out << "/* Helper union for bitcasts */\n"; + Out << "typedef union {\n"; + Out << " unsigned int Int32;\n"; + Out << " unsigned long long Int64;\n"; + Out << " float Float;\n"; + Out << " double Double;\n"; + Out << "} llvmBitCastUnion;\n"; + + // Get all of the struct types used in the module. + std::vector StructTypes; + TheModule->findUsedStructTypes(StructTypes); + + if (StructTypes.empty()) return; + + Out << "/* Structure forward decls */\n"; + + unsigned NextTypeID = 0; + + // If any of them are missing names, add a unique ID to UnnamedStructIDs. + // Print out forward declarations for structure types. + for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) { + StructType *ST = StructTypes[i]; + + if (ST->isLiteral() || ST->getName().empty()) + UnnamedStructIDs[ST] = NextTypeID++; + + std::string Name = getStructName(ST); + + Out << "typedef struct " << Name << ' ' << Name << ";\n"; + } + + Out << '\n'; + + // Keep track of which structures have been printed so far. + SmallPtrSet StructPrinted; + + // Loop over all structures then push them into the stack so they are + // printed in the correct order. + // + Out << "/* Structure contents */\n"; + for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) + if (StructTypes[i]->isStructTy()) + // Only print out used types! + printContainedStructs(StructTypes[i], StructPrinted); +} + +// Push the struct onto the stack and recursively push all structs +// this one depends on. +// +// TODO: Make this work properly with vector types +// +void GenWriter::printContainedStructs(Type *Ty, + SmallPtrSet &StructPrinted) { + // Don't walk through pointers. + if (Ty->isPointerTy() || Ty->isPrimitiveType() || Ty->isIntegerTy()) + return; + + // Print all contained types first. + for (Type::subtype_iterator I = Ty->subtype_begin(), + E = Ty->subtype_end(); I != E; ++I) + printContainedStructs(*I, StructPrinted); + + if (StructType *ST = dyn_cast(Ty)) { + // Check to see if we have already printed this struct. + if (!StructPrinted.insert(Ty)) return; + + // Print structure type out. + printType(Out, ST, false, getStructName(ST), true); + Out << ";\n\n"; + } +} + +void GenWriter::printFunctionSignature(const Function *F, bool Prototype) { + /// isStructReturn - Should this function actually return a struct by-value? + bool isStructReturn = F->hasStructRetAttr(); + + if (F->hasLocalLinkage()) Out << "static "; + if (F->hasDLLImportLinkage()) Out << "__declspec(dllimport) "; + if (F->hasDLLExportLinkage()) Out << "__declspec(dllexport) "; + switch (F->getCallingConv()) { + case CallingConv::X86_StdCall: + Out << "__attribute__((stdcall)) "; + break; + case CallingConv::X86_FastCall: + Out << "__attribute__((fastcall)) "; + break; + case CallingConv::X86_ThisCall: + Out << "__attribute__((thiscall)) "; + break; + default: + break; + } + + // Loop over the arguments, printing them... + FunctionType *FT = cast(F->getFunctionType()); + const AttrListPtr &PAL = F->getAttributes(); + + std::string tstr; + raw_string_ostream FunctionInnards(tstr); + + // Print out the name... + FunctionInnards << GetValueName(F) << '('; + + bool PrintedArg = false; + if (!F->isDeclaration()) { + if (!F->arg_empty()) { + Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); + unsigned Idx = 1; + + // If this is a struct-return function, don't print the hidden + // struct-return argument. + if (isStructReturn) { + assert(I != E && "Invalid struct return function!"); + ++I; + ++Idx; + } + + std::string ArgName; + for (; I != E; ++I) { + if (PrintedArg) FunctionInnards << ", "; + if (I->hasName() || !Prototype) + ArgName = GetValueName(I); + else + ArgName = ""; + Type *ArgTy = I->getType(); + if (PAL.paramHasAttr(Idx, Attribute::ByVal)) { + ArgTy = cast(ArgTy)->getElementType(); + ByValParams.insert(I); + } + printType(FunctionInnards, ArgTy, + /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt), + ArgName); + PrintedArg = true; + ++Idx; + } + } + } else { + // Loop over the arguments, printing them. + FunctionType::param_iterator I = FT->param_begin(), E = FT->param_end(); + unsigned Idx = 1; + + // If this is a struct-return function, don't print the hidden + // struct-return argument. + if (isStructReturn) { + assert(I != E && "Invalid struct return function!"); + ++I; + ++Idx; + } + + for (; I != E; ++I) { + if (PrintedArg) FunctionInnards << ", "; + Type *ArgTy = *I; + if (PAL.paramHasAttr(Idx, Attribute::ByVal)) { + assert(ArgTy->isPointerTy()); + ArgTy = cast(ArgTy)->getElementType(); + } + printType(FunctionInnards, ArgTy, + /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt)); + PrintedArg = true; + ++Idx; + } + } + + if (!PrintedArg && FT->isVarArg()) { + FunctionInnards << "int vararg_dummy_arg"; + PrintedArg = true; + } + + // Finish printing arguments... if this is a vararg function, print the ..., + // unless there are no known types, in which case, we just emit (). + // + if (FT->isVarArg() && PrintedArg) { + FunctionInnards << ",..."; // Output varargs portion of signature! + } else if (!FT->isVarArg() && !PrintedArg) { + FunctionInnards << "void"; // ret() -> ret(void) in C. + } + FunctionInnards << ')'; + + // Get the return tpe for the function. + Type *RetTy; + if (!isStructReturn) + RetTy = F->getReturnType(); + else { + // If this is a struct-return function, print the struct-return type. + RetTy = cast(FT->getParamType(0))->getElementType(); + } + + // Print out the return type and the signature built above. + printType(Out, RetTy, + /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), + FunctionInnards.str()); +} + +static inline bool isFPIntBitCast(const Instruction &I) { + if (!isa(I)) + return false; + Type *SrcTy = I.getOperand(0)->getType(); + Type *DstTy = I.getType(); + return (SrcTy->isFloatingPointTy() && DstTy->isIntegerTy()) || + (DstTy->isFloatingPointTy() && SrcTy->isIntegerTy()); +} + +void GenWriter::printFunction(Function &F) { + /// isStructReturn - Should this function actually return a struct by-value? + bool isStructReturn = F.hasStructRetAttr(); + + printFunctionSignature(&F, false); + Out << " {\n"; + + // If this is a struct return function, handle the result with magic. + if (isStructReturn) { + Type *StructTy = + cast(F.arg_begin()->getType())->getElementType(); + Out << " "; + printType(Out, StructTy, false, "StructReturn"); + Out << "; /* Struct return temporary */\n"; + + Out << " "; + printType(Out, F.arg_begin()->getType(), false, + GetValueName(F.arg_begin())); + Out << " = &StructReturn;\n"; + } + + bool PrintedVar = false; + + // print local variable information for the function + for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) { + if (const AllocaInst *AI = isDirectAlloca(&*I)) { + Out << " "; + printType(Out, AI->getAllocatedType(), false, GetValueName(AI)); + Out << "; /* Address-exposed local */\n"; + PrintedVar = true; + } else if (I->getType() != Type::getVoidTy(F.getContext()) && + !isInlinableInst(*I)) { + Out << " "; + printType(Out, I->getType(), false, GetValueName(&*I)); + Out << ";\n"; + + if (isa(*I)) { // Print out PHI node temporaries as well... + Out << " "; + printType(Out, I->getType(), false, + GetValueName(&*I)+"__PHI_TEMPORARY"); + Out << ";\n"; + } + PrintedVar = true; + } + // We need a temporary for the BitCast to use so it can pluck a value out + // of a union to do the BitCast. This is separate from the need for a + // variable to hold the result of the BitCast. + if (isFPIntBitCast(*I)) { + Out << " llvmBitCastUnion " << GetValueName(&*I) + << "__BITCAST_TEMPORARY;\n"; + PrintedVar = true; + } + } + + if (PrintedVar) + Out << '\n'; + + if (F.hasExternalLinkage() && F.getName() == "main") + Out << " CODE_FOR_MAIN();\n"; + + // print the basic blocks + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (Loop *L = LI->getLoopFor(BB)) { + if (L->getHeader() == BB && L->getParentLoop() == 0) + printLoop(L); + } else { + printBasicBlock(BB); + } + } + + Out << "}\n\n"; +} + +void GenWriter::printLoop(Loop *L) { + Out << " do { /* Syntactic loop '" << L->getHeader()->getName() + << "' to make GCC happy */\n"; + for (unsigned i = 0, e = L->getBlocks().size(); i != e; ++i) { + BasicBlock *BB = L->getBlocks()[i]; + Loop *BBLoop = LI->getLoopFor(BB); + if (BBLoop == L) + printBasicBlock(BB); + else if (BB == BBLoop->getHeader() && BBLoop->getParentLoop() == L) + printLoop(BBLoop); + } + Out << " } while (1); /* end of syntactic loop '" + << L->getHeader()->getName() << "' */\n"; +} + +void GenWriter::printBasicBlock(BasicBlock *BB) { + + // Don't print the label for the basic block if there are no uses, or if + // the only terminator use is the predecessor basic block's terminator. + // We have to scan the use list because PHI nodes use basic blocks too but + // do not require a label to be generated. + // + bool NeedsLabel = false; + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + if (isGotoCodeNecessary(*PI, BB)) { + NeedsLabel = true; + break; + } + + if (NeedsLabel) Out << GetValueName(BB) << ":\n"; + + // Output all of the instructions in the basic block... + for (BasicBlock::iterator II = BB->begin(), E = --BB->end(); II != E; + ++II) { + if (!isInlinableInst(*II) && !isDirectAlloca(II)) { + if (II->getType() != Type::getVoidTy(BB->getContext()) && + !isInlineAsm(*II)) + outputLValue(II); + else + Out << " "; + writeInstComputationInline(*II); + Out << ";\n"; + } + } + + // Don't emit prefix or suffix for the terminator. + visit(*BB->getTerminator()); +} + + +// Specific Instruction type classes... note that all of the casts are +// necessary because we use the instruction classes as opaque types... +// +void GenWriter::visitReturnInst(ReturnInst &I) { + // If this is a struct return function, return the temporary struct. + bool isStructReturn = I.getParent()->getParent()->hasStructRetAttr(); + + if (isStructReturn) { + Out << " return StructReturn;\n"; + return; + } + + // Don't output a void return if this is the last basic block in the function + if (I.getNumOperands() == 0 && + &*--I.getParent()->getParent()->end() == I.getParent() && + !I.getParent()->size() == 1) { + return; + } + + Out << " return"; + if (I.getNumOperands()) { + Out << ' '; + writeOperand(I.getOperand(0)); + } + Out << ";\n"; +} + +void GenWriter::visitSwitchInst(SwitchInst &SI) { + + Value* Cond = SI.getCondition(); + + Out << " switch ("; + writeOperand(Cond); + Out << ") {\n default:\n"; + printPHICopiesForSuccessor (SI.getParent(), SI.getDefaultDest(), 2); + printBranchToBlock(SI.getParent(), SI.getDefaultDest(), 2); + Out << ";\n"; + + unsigned NumCases = SI.getNumCases(); + // Skip the first item since that's the default case. + for (unsigned i = 1; i < NumCases; ++i) { + ConstantInt* CaseVal = SI.getCaseValue(i); + BasicBlock* Succ = SI.getSuccessor(i); + Out << " case "; + writeOperand(CaseVal); + Out << ":\n"; + printPHICopiesForSuccessor (SI.getParent(), Succ, 2); + printBranchToBlock(SI.getParent(), Succ, 2); + if (Function::iterator(Succ) == llvm::next(Function::iterator(SI.getParent()))) + Out << " break;\n"; + } + + Out << " }\n"; +} + +void GenWriter::visitIndirectBrInst(IndirectBrInst &IBI) { + Out << " goto *(void*)("; + writeOperand(IBI.getOperand(0)); + Out << ");\n"; +} + +void GenWriter::visitUnreachableInst(UnreachableInst &I) { + Out << " /*UNREACHABLE*/;\n"; +} + +bool GenWriter::isGotoCodeNecessary(BasicBlock *From, BasicBlock *To) { + /// FIXME: This should be reenabled, but loop reordering safe!! + return true; + + if (llvm::next(Function::iterator(From)) != Function::iterator(To)) + return true; // Not the direct successor, we need a goto. + + //isa(From->getTerminator()) + + if (LI->getLoopFor(From) != LI->getLoopFor(To)) + return true; + return false; +} + +void GenWriter::printPHICopiesForSuccessor (BasicBlock *CurBlock, + BasicBlock *Successor, + unsigned Indent) { + for (BasicBlock::iterator I = Successor->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + // Now we have to do the printing. + Value *IV = PN->getIncomingValueForBlock(CurBlock); + if (!isa(IV)) { + Out << std::string(Indent, ' '); + Out << " " << GetValueName(I) << "__PHI_TEMPORARY = "; + writeOperand(IV); + Out << "; /* for PHI node */\n"; + } + } +} + +void GenWriter::printBranchToBlock(BasicBlock *CurBB, BasicBlock *Succ, + unsigned Indent) { + if (isGotoCodeNecessary(CurBB, Succ)) { + Out << std::string(Indent, ' ') << " goto "; + writeOperand(Succ); + Out << ";\n"; + } +} + +// Branch instruction printing - Avoid printing out a branch to a basic block +// that immediately succeeds the current one. +// +void GenWriter::visitBranchInst(BranchInst &I) { + + if (I.isConditional()) { + if (isGotoCodeNecessary(I.getParent(), I.getSuccessor(0))) { + Out << " if ("; + writeOperand(I.getCondition()); + Out << ") {\n"; + + printPHICopiesForSuccessor (I.getParent(), I.getSuccessor(0), 2); + printBranchToBlock(I.getParent(), I.getSuccessor(0), 2); + + if (isGotoCodeNecessary(I.getParent(), I.getSuccessor(1))) { + Out << " } else {\n"; + printPHICopiesForSuccessor (I.getParent(), I.getSuccessor(1), 2); + printBranchToBlock(I.getParent(), I.getSuccessor(1), 2); + } + } else { + // First goto not necessary, assume second one is... + Out << " if (!"; + writeOperand(I.getCondition()); + Out << ") {\n"; + + printPHICopiesForSuccessor (I.getParent(), I.getSuccessor(1), 2); + printBranchToBlock(I.getParent(), I.getSuccessor(1), 2); + } + + Out << " }\n"; + } else { + printPHICopiesForSuccessor (I.getParent(), I.getSuccessor(0), 0); + printBranchToBlock(I.getParent(), I.getSuccessor(0), 0); + } + Out << "\n"; +} + +// PHI nodes get copied into temporary values at the end of predecessor basic +// blocks. We now need to copy these temporary values into the REAL value for +// the PHI. +void GenWriter::visitPHINode(PHINode &I) { + writeOperand(&I); + Out << "__PHI_TEMPORARY"; +} + + +void GenWriter::visitBinaryOperator(Instruction &I) { + // binary instructions, shift instructions, setCond instructions. + assert(!I.getType()->isPointerTy()); + + // We must cast the results of binary operations which might be promoted. + bool needsCast = false; + if ((I.getType() == Type::getInt8Ty(I.getContext())) || + (I.getType() == Type::getInt16Ty(I.getContext())) + || (I.getType() == Type::getFloatTy(I.getContext()))) { + needsCast = true; + Out << "(("; + printType(Out, I.getType(), false); + Out << ")("; + } + + // If this is a negation operation, print it out as such. For FP, we don't + // want to print "-0.0 - X". + if (BinaryOperator::isNeg(&I)) { + Out << "-("; + writeOperand(BinaryOperator::getNegArgument(cast(&I))); + Out << ")"; + } else if (BinaryOperator::isFNeg(&I)) { + Out << "-("; + writeOperand(BinaryOperator::getFNegArgument(cast(&I))); + Out << ")"; + } else if (I.getOpcode() == Instruction::FRem) { + // Output a call to fmod/fmodf instead of emitting a%b + if (I.getType() == Type::getFloatTy(I.getContext())) + Out << "fmodf("; + else if (I.getType() == Type::getDoubleTy(I.getContext())) + Out << "fmod("; + else // all 3 flavors of long double + Out << "fmodl("; + writeOperand(I.getOperand(0)); + Out << ", "; + writeOperand(I.getOperand(1)); + Out << ")"; + } else { + + // Write out the cast of the instruction's value back to the proper type + // if necessary. + bool NeedsClosingParens = writeInstructionCast(I); + + // Certain instructions require the operand to be forced to a specific type + // so we use writeOperandWithCast here instead of writeOperand. Similarly + // below for operand 1 + writeOperandWithCast(I.getOperand(0), I.getOpcode()); + + switch (I.getOpcode()) { + case Instruction::Add: + case Instruction::FAdd: Out << " + "; break; + case Instruction::Sub: + case Instruction::FSub: Out << " - "; break; + case Instruction::Mul: + case Instruction::FMul: Out << " * "; break; + case Instruction::URem: + case Instruction::SRem: + case Instruction::FRem: Out << " % "; break; + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::FDiv: Out << " / "; break; + case Instruction::And: Out << " & "; break; + case Instruction::Or: Out << " | "; break; + case Instruction::Xor: Out << " ^ "; break; + case Instruction::Shl : Out << " << "; break; + case Instruction::LShr: + case Instruction::AShr: Out << " >> "; break; + default: +#ifndef NDEBUG + errs() << "Invalid operator type!" << I; +#endif + llvm_unreachable(0); + } + + writeOperandWithCast(I.getOperand(1), I.getOpcode()); + if (NeedsClosingParens) + Out << "))"; + } + + if (needsCast) { + Out << "))"; + } +} + +void GenWriter::visitICmpInst(ICmpInst &I) { + // We must cast the results of icmp which might be promoted. + bool needsCast = false; + + // Write out the cast of the instruction's value back to the proper type + // if necessary. + bool NeedsClosingParens = writeInstructionCast(I); + + // Certain icmp predicate require the operand to be forced to a specific type + // so we use writeOperandWithCast here instead of writeOperand. Similarly + // below for operand 1 + writeOperandWithCast(I.getOperand(0), I); + + switch (I.getPredicate()) { + case ICmpInst::ICMP_EQ: Out << " == "; break; + case ICmpInst::ICMP_NE: Out << " != "; break; + case ICmpInst::ICMP_ULE: + case ICmpInst::ICMP_SLE: Out << " <= "; break; + case ICmpInst::ICMP_UGE: + case ICmpInst::ICMP_SGE: Out << " >= "; break; + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_SLT: Out << " < "; break; + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_SGT: Out << " > "; break; + default: +#ifndef NDEBUG + errs() << "Invalid icmp predicate!" << I; +#endif + llvm_unreachable(0); + } + + writeOperandWithCast(I.getOperand(1), I); + if (NeedsClosingParens) + Out << "))"; + + if (needsCast) { + Out << "))"; + } +} + +void GenWriter::visitFCmpInst(FCmpInst &I) { + if (I.getPredicate() == FCmpInst::FCMP_FALSE) { + Out << "0"; + return; + } + if (I.getPredicate() == FCmpInst::FCMP_TRUE) { + Out << "1"; + return; + } + + const char* op = 0; + switch (I.getPredicate()) { + default: llvm_unreachable("Illegal FCmp predicate"); + case FCmpInst::FCMP_ORD: op = "ord"; break; + case FCmpInst::FCMP_UNO: op = "uno"; break; + case FCmpInst::FCMP_UEQ: op = "ueq"; break; + case FCmpInst::FCMP_UNE: op = "une"; break; + case FCmpInst::FCMP_ULT: op = "ult"; break; + case FCmpInst::FCMP_ULE: op = "ule"; break; + case FCmpInst::FCMP_UGT: op = "ugt"; break; + case FCmpInst::FCMP_UGE: op = "uge"; break; + case FCmpInst::FCMP_OEQ: op = "oeq"; break; + case FCmpInst::FCMP_ONE: op = "one"; break; + case FCmpInst::FCMP_OLT: op = "olt"; break; + case FCmpInst::FCMP_OLE: op = "ole"; break; + case FCmpInst::FCMP_OGT: op = "ogt"; break; + case FCmpInst::FCMP_OGE: op = "oge"; break; + } + + Out << "llvm_fcmp_" << op << "("; + // Write the first operand + writeOperand(I.getOperand(0)); + Out << ", "; + // Write the second operand + writeOperand(I.getOperand(1)); + Out << ")"; +} + +static const char * getFloatBitCastField(Type *Ty) { + switch (Ty->getTypeID()) { + default: llvm_unreachable("Invalid Type"); + case Type::FloatTyID: return "Float"; + case Type::DoubleTyID: return "Double"; + case Type::IntegerTyID: { + unsigned NumBits = cast(Ty)->getBitWidth(); + if (NumBits <= 32) + return "Int32"; + else + return "Int64"; + } + } +} + +void GenWriter::visitCastInst(CastInst &I) { + Type *DstTy = I.getType(); + Type *SrcTy = I.getOperand(0)->getType(); + if (isFPIntBitCast(I)) { + Out << '('; + // These int<->float and long<->double casts need to be handled specially + Out << GetValueName(&I) << "__BITCAST_TEMPORARY." + << getFloatBitCastField(I.getOperand(0)->getType()) << " = "; + writeOperand(I.getOperand(0)); + Out << ", " << GetValueName(&I) << "__BITCAST_TEMPORARY." + << getFloatBitCastField(I.getType()); + Out << ')'; + return; + } + + Out << '('; + printCast(I.getOpcode(), SrcTy, DstTy); + + // Make a sext from i1 work by subtracting the i1 from 0 (an int). + if (SrcTy == Type::getInt1Ty(I.getContext()) && + I.getOpcode() == Instruction::SExt) + Out << "0-"; + + writeOperand(I.getOperand(0)); + + if (DstTy == Type::getInt1Ty(I.getContext()) && + (I.getOpcode() == Instruction::Trunc || + I.getOpcode() == Instruction::FPToUI || + I.getOpcode() == Instruction::FPToSI || + I.getOpcode() == Instruction::PtrToInt)) { + // Make sure we really get a trunc to bool by anding the operand with 1 + Out << "&1u"; + } + Out << ')'; +} + +void GenWriter::visitSelectInst(SelectInst &I) { + Out << "(("; + writeOperand(I.getCondition()); + Out << ") ? ("; + writeOperand(I.getTrueValue()); + Out << ") : ("; + writeOperand(I.getFalseValue()); + Out << "))"; +} + +// Returns the macro name or value of the max or min of an integer type +// (as defined in limits.h). +static void printLimitValue(IntegerType &Ty, bool isSigned, bool isMax, + raw_ostream &Out) { + const char* type; + const char* sprefix = ""; + + unsigned NumBits = Ty.getBitWidth(); + if (NumBits <= 8) { + type = "CHAR"; + sprefix = "S"; + } else if (NumBits <= 16) { + type = "SHRT"; + } else if (NumBits <= 32) { + type = "INT"; + } else if (NumBits <= 64) { + type = "LLONG"; + } else { + llvm_unreachable("Bit widths > 64 not implemented yet"); + } + + if (isSigned) + Out << sprefix << type << (isMax ? "_MAX" : "_MIN"); + else + Out << "U" << type << (isMax ? "_MAX" : "0"); +} + +#ifndef NDEBUG +static bool isSupportedIntegerSize(IntegerType &T) { + return T.getBitWidth() == 8 || T.getBitWidth() == 16 || + T.getBitWidth() == 32 || T.getBitWidth() == 64; +} +#endif + +void GenWriter::printIntrinsicDefinition(const Function &F, raw_ostream &Out) { + FunctionType *funT = F.getFunctionType(); + Type *retT = F.getReturnType(); + IntegerType *elemT = cast(funT->getParamType(1)); + + assert(isSupportedIntegerSize(*elemT) && + "CBackend does not support arbitrary size integers."); + assert(cast(retT)->getElementType(0) == elemT && + elemT == funT->getParamType(0) && funT->getNumParams() == 2); + + switch (F.getIntrinsicID()) { + default: + llvm_unreachable("Unsupported Intrinsic."); + case Intrinsic::uadd_with_overflow: + // static inline Rty uadd_ixx(unsigned ixx a, unsigned ixx b) { + // Rty r; + // r.field0 = a + b; + // r.field1 = (r.field0 < a); + // return r; + // } + Out << "static inline "; + printType(Out, retT); + Out << GetValueName(&F); + Out << "("; + printSimpleType(Out, elemT, false); + Out << "a,"; + printSimpleType(Out, elemT, false); + Out << "b) {\n "; + printType(Out, retT); + Out << "r;\n"; + Out << " r.field0 = a + b;\n"; + Out << " r.field1 = (r.field0 < a);\n"; + Out << " return r;\n}\n"; + break; + + case Intrinsic::sadd_with_overflow: + // static inline Rty sadd_ixx(ixx a, ixx b) { + // Rty r; + // r.field1 = (b > 0 && a > XX_MAX - b) || + // (b < 0 && a < XX_MIN - b); + // r.field0 = r.field1 ? 0 : a + b; + // return r; + // } + Out << "static "; + printType(Out, retT); + Out << GetValueName(&F); + Out << "("; + printSimpleType(Out, elemT, true); + Out << "a,"; + printSimpleType(Out, elemT, true); + Out << "b) {\n "; + printType(Out, retT); + Out << "r;\n"; + Out << " r.field1 = (b > 0 && a > "; + printLimitValue(*elemT, true, true, Out); + Out << " - b) || (b < 0 && a < "; + printLimitValue(*elemT, true, false, Out); + Out << " - b);\n"; + Out << " r.field0 = r.field1 ? 0 : a + b;\n"; + Out << " return r;\n}\n"; + break; + } +} + +void GenWriter::lowerIntrinsics(Function &F) { + // This is used to keep track of intrinsics that get generated to a lowered + // function. We must generate the prototypes before the function body which + // will only be expanded on first use (by the loop below). + std::vector prototypesToGen; + + // Examine all the instructions in this function to find the intrinsics that + // need to be lowered. + for (Function::iterator BB = F.begin(), EE = F.end(); BB != EE; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) + if (CallInst *CI = dyn_cast(I++)) + if (Function *F = CI->getCalledFunction()) + switch (F->getIntrinsicID()) { + case Intrinsic::not_intrinsic: + case Intrinsic::vastart: + case Intrinsic::vacopy: + case Intrinsic::vaend: + case Intrinsic::returnaddress: + case Intrinsic::frameaddress: + case Intrinsic::setjmp: + case Intrinsic::longjmp: + case Intrinsic::prefetch: + case Intrinsic::powi: + case Intrinsic::x86_sse_cmp_ss: + case Intrinsic::x86_sse_cmp_ps: + case Intrinsic::x86_sse2_cmp_sd: + case Intrinsic::x86_sse2_cmp_pd: + case Intrinsic::ppc_altivec_lvsl: + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + // We directly implement these intrinsics + break; + default: + // If this is an intrinsic that directly corresponds to a GCC + // builtin, we handle it. + const char *BuiltinName = ""; +#define GET_GCC_BUILTIN_NAME +#include "llvm/Intrinsics.gen" +#undef GET_GCC_BUILTIN_NAME + // If we handle it, don't lower it. + if (BuiltinName[0]) break; + + // All other intrinsic calls we must lower. + Instruction *Before = 0; + if (CI != &BB->front()) + Before = prior(BasicBlock::iterator(CI)); + + IL->LowerIntrinsicCall(CI); + if (Before) { // Move iterator to instruction after call + I = Before; ++I; + } else { + I = BB->begin(); + } + // If the intrinsic got lowered to another call, and that call has + // a definition then we need to make sure its prototype is emitted + // before any calls to it. + if (CallInst *Call = dyn_cast(I)) + if (Function *NewF = Call->getCalledFunction()) + if (!NewF->isDeclaration()) + prototypesToGen.push_back(NewF); + + break; + } + + // We may have collected some prototypes to emit in the loop above. + // Emit them now, before the function that uses them is emitted. But, + // be careful not to emit them twice. + std::vector::iterator I = prototypesToGen.begin(); + std::vector::iterator E = prototypesToGen.end(); + for ( ; I != E; ++I) { + if (intrinsicPrototypesAlreadyGenerated.insert(*I).second) { + Out << '\n'; + printFunctionSignature(*I, true); + Out << ";\n"; + } + } +} + +void GenWriter::visitCallInst(CallInst &I) { + if (isa(I.getCalledValue())) + return visitInlineAsm(I); + + bool WroteCallee = false; + + // Handle intrinsic function calls first... + if (Function *F = I.getCalledFunction()) + if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) + if (visitBuiltinCall(I, ID, WroteCallee)) + return; + + Value *Callee = I.getCalledValue(); + + PointerType *PTy = cast(Callee->getType()); + FunctionType *FTy = cast(PTy->getElementType()); + + // If this is a call to a struct-return function, assign to the first + // parameter instead of passing it to the call. + const AttrListPtr &PAL = I.getAttributes(); + bool hasByVal = I.hasByValArgument(); + bool isStructRet = I.hasStructRetAttr(); + if (isStructRet) { + writeOperandDeref(I.getArgOperand(0)); + Out << " = "; + } + + if (I.isTailCall()) Out << " /*tail*/ "; + + if (!WroteCallee) { + // If this is an indirect call to a struct return function, we need to cast + // the pointer. Ditto for indirect calls with byval arguments. + bool NeedsCast = (hasByVal || isStructRet) && !isa(Callee); + + // GCC is a real PITA. It does not permit codegening casts of functions to + // function pointers if they are in a call (it generates a trap instruction + // instead!). We work around this by inserting a cast to void* in between + // the function and the function pointer cast. Unfortunately, we can't just + // form the constant expression here, because the folder will immediately + // nuke it. + // + // Note finally, that this is completely unsafe. ANSI C does not guarantee + // that void* and function pointers have the same size. :( To deal with this + // in the common case, we handle casts where the number of arguments passed + // match exactly. + // + if (ConstantExpr *CE = dyn_cast(Callee)) + if (CE->isCast()) + if (Function *RF = dyn_cast(CE->getOperand(0))) { + NeedsCast = true; + Callee = RF; + } + + if (NeedsCast) { + // Ok, just cast the pointer type. + Out << "(("; + if (isStructRet) + printStructReturnPointerFunctionType(Out, PAL, + cast(I.getCalledValue()->getType())); + else if (hasByVal) + printType(Out, I.getCalledValue()->getType(), false, "", true, PAL); + else + printType(Out, I.getCalledValue()->getType()); + Out << ")(void*)"; + } + writeOperand(Callee); + if (NeedsCast) Out << ')'; + } + + Out << '('; + + bool PrintedArg = false; + if(FTy->isVarArg() && !FTy->getNumParams()) { + Out << "0 /*dummy arg*/"; + PrintedArg = true; + } + + unsigned NumDeclaredParams = FTy->getNumParams(); + CallSite CS(&I); + CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); + unsigned ArgNo = 0; + if (isStructRet) { // Skip struct return argument. + ++AI; + ++ArgNo; + } + + + for (; AI != AE; ++AI, ++ArgNo) { + if (PrintedArg) Out << ", "; + if (ArgNo < NumDeclaredParams && + (*AI)->getType() != FTy->getParamType(ArgNo)) { + Out << '('; + printType(Out, FTy->getParamType(ArgNo), + /*isSigned=*/PAL.paramHasAttr(ArgNo+1, Attribute::SExt)); + Out << ')'; + } + // Check if the argument is expected to be passed by value. + if (I.paramHasAttr(ArgNo+1, Attribute::ByVal)) + writeOperandDeref(*AI); + else + writeOperand(*AI); + PrintedArg = true; + } + Out << ')'; +} + +/// visitBuiltinCall - Handle the call to the specified builtin. Returns true +/// if the entire call is handled, return false if it wasn't handled, and +/// optionally set 'WroteCallee' if the callee has already been printed out. +bool GenWriter::visitBuiltinCall(CallInst &I, Intrinsic::ID ID, + bool &WroteCallee) { + switch (ID) { + default: { + // If this is an intrinsic that directly corresponds to a GCC + // builtin, we emit it here. + const char *BuiltinName = ""; + Function *F = I.getCalledFunction(); +#define GET_GCC_BUILTIN_NAME +#include "llvm/Intrinsics.gen" +#undef GET_GCC_BUILTIN_NAME + assert(BuiltinName[0] && "Unknown LLVM intrinsic!"); + + Out << BuiltinName; + WroteCallee = true; + return false; + } + case Intrinsic::vastart: + Out << "0; "; + + Out << "va_start(*(va_list*)"; + writeOperand(I.getArgOperand(0)); + Out << ", "; + // Output the last argument to the enclosing function. + if (I.getParent()->getParent()->arg_empty()) + Out << "vararg_dummy_arg"; + else + writeOperand(--I.getParent()->getParent()->arg_end()); + Out << ')'; + return true; + case Intrinsic::vaend: + if (!isa(I.getArgOperand(0))) { + Out << "0; va_end(*(va_list*)"; + writeOperand(I.getArgOperand(0)); + Out << ')'; + } else { + Out << "va_end(*(va_list*)0)"; + } + return true; + case Intrinsic::vacopy: + Out << "0; "; + Out << "va_copy(*(va_list*)"; + writeOperand(I.getArgOperand(0)); + Out << ", *(va_list*)"; + writeOperand(I.getArgOperand(1)); + Out << ')'; + return true; + case Intrinsic::returnaddress: + Out << "__builtin_return_address("; + writeOperand(I.getArgOperand(0)); + Out << ')'; + return true; + case Intrinsic::frameaddress: + Out << "__builtin_frame_address("; + writeOperand(I.getArgOperand(0)); + Out << ')'; + return true; + case Intrinsic::powi: + Out << "__builtin_powi("; + writeOperand(I.getArgOperand(0)); + Out << ", "; + writeOperand(I.getArgOperand(1)); + Out << ')'; + return true; + case Intrinsic::setjmp: + Out << "setjmp(*(jmp_buf*)"; + writeOperand(I.getArgOperand(0)); + Out << ')'; + return true; + case Intrinsic::longjmp: + Out << "longjmp(*(jmp_buf*)"; + writeOperand(I.getArgOperand(0)); + Out << ", "; + writeOperand(I.getArgOperand(1)); + Out << ')'; + return true; + case Intrinsic::prefetch: + Out << "LLVM_PREFETCH((const void *)"; + writeOperand(I.getArgOperand(0)); + Out << ", "; + writeOperand(I.getArgOperand(1)); + Out << ", "; + writeOperand(I.getArgOperand(2)); + Out << ")"; + return true; + case Intrinsic::stacksave: + // Emit this as: Val = 0; *((void**)&Val) = __builtin_stack_save() + // to work around GCC bugs (see PR1809). + Out << "0; *((void**)&" << GetValueName(&I) + << ") = __builtin_stack_save()"; + return true; + case Intrinsic::x86_sse_cmp_ss: + case Intrinsic::x86_sse_cmp_ps: + case Intrinsic::x86_sse2_cmp_sd: + case Intrinsic::x86_sse2_cmp_pd: + Out << '('; + printType(Out, I.getType()); + Out << ')'; + // Multiple GCC builtins multiplex onto this intrinsic. + switch (cast(I.getArgOperand(2))->getZExtValue()) { + default: llvm_unreachable("Invalid llvm.x86.sse.cmp!"); + case 0: Out << "__builtin_ia32_cmpeq"; break; + case 1: Out << "__builtin_ia32_cmplt"; break; + case 2: Out << "__builtin_ia32_cmple"; break; + case 3: Out << "__builtin_ia32_cmpunord"; break; + case 4: Out << "__builtin_ia32_cmpneq"; break; + case 5: Out << "__builtin_ia32_cmpnlt"; break; + case 6: Out << "__builtin_ia32_cmpnle"; break; + case 7: Out << "__builtin_ia32_cmpord"; break; + } + if (ID == Intrinsic::x86_sse_cmp_ps || ID == Intrinsic::x86_sse2_cmp_pd) + Out << 'p'; + else + Out << 's'; + if (ID == Intrinsic::x86_sse_cmp_ss || ID == Intrinsic::x86_sse_cmp_ps) + Out << 's'; + else + Out << 'd'; + + Out << "("; + writeOperand(I.getArgOperand(0)); + Out << ", "; + writeOperand(I.getArgOperand(1)); + Out << ")"; + return true; + case Intrinsic::ppc_altivec_lvsl: + Out << '('; + printType(Out, I.getType()); + Out << ')'; + Out << "__builtin_altivec_lvsl(0, (void*)"; + writeOperand(I.getArgOperand(0)); + Out << ")"; + return true; + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + Out << GetValueName(I.getCalledFunction()) << "("; + writeOperand(I.getArgOperand(0)); + Out << ", "; + writeOperand(I.getArgOperand(1)); + Out << ")"; + return true; + } +} + +//This converts the llvm constraint string to something gcc is expecting. +//TODO: work out platform independent constraints and factor those out +// of the per target tables +// handle multiple constraint codes +std::string GenWriter::InterpretASMConstraint(InlineAsm::ConstraintInfo& c) { + assert(c.Codes.size() == 1 && "Too many asm constraint codes to handle"); + + // Grab the translation table from MCAsmInfo if it exists. + const MCAsmInfo *TargetAsm; + std::string Triple = TheModule->getTargetTriple(); + if (Triple.empty()) + Triple = llvm::sys::getHostTriple(); + + std::string E; + if (const Target *Match = TargetRegistry::lookupTarget(Triple, E)) + TargetAsm = Match->createMCAsmInfo(Triple); + else + return c.Codes[0]; + + const char *const *table = TargetAsm->getAsmCBE(); + + // Search the translation table if it exists. + for (int i = 0; table && table[i]; i += 2) + if (c.Codes[0] == table[i]) { + delete TargetAsm; + return table[i+1]; + } + + // Default is identity. + delete TargetAsm; + return c.Codes[0]; +} + +//TODO: import logic from AsmPrinter.cpp +static std::string gccifyAsm(std::string asmstr) { + for (std::string::size_type i = 0; i != asmstr.size(); ++i) + if (asmstr[i] == '\n') + asmstr.replace(i, 1, "\\n"); + else if (asmstr[i] == '\t') + asmstr.replace(i, 1, "\\t"); + else if (asmstr[i] == '$') { + if (asmstr[i + 1] == '{') { + std::string::size_type a = asmstr.find_first_of(':', i + 1); + std::string::size_type b = asmstr.find_first_of('}', i + 1); + std::string n = "%" + + asmstr.substr(a + 1, b - a - 1) + + asmstr.substr(i + 2, a - i - 2); + asmstr.replace(i, b - i + 1, n); + i += n.size() - 1; + } else + asmstr.replace(i, 1, "%"); + } + else if (asmstr[i] == '%')//grr + { asmstr.replace(i, 1, "%%"); ++i;} + + return asmstr; +} + +//TODO: assumptions about what consume arguments from the call are likely wrong +// handle communitivity +void GenWriter::visitInlineAsm(CallInst &CI) { + InlineAsm* as = cast(CI.getCalledValue()); + InlineAsm::ConstraintInfoVector Constraints = as->ParseConstraints(); + + std::vector > ResultVals; + if (CI.getType() == Type::getVoidTy(CI.getContext())) + ; + else if (StructType *ST = dyn_cast(CI.getType())) { + for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) + ResultVals.push_back(std::make_pair(&CI, (int)i)); + } else { + ResultVals.push_back(std::make_pair(&CI, -1)); + } + + // Fix up the asm string for gcc and emit it. + Out << "__asm__ volatile (\"" << gccifyAsm(as->getAsmString()) << "\"\n"; + Out << " :"; + + unsigned ValueCount = 0; + bool IsFirst = true; + + // Convert over all the output constraints. + for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), + E = Constraints.end(); I != E; ++I) { + + if (I->Type != InlineAsm::isOutput) { + ++ValueCount; + continue; // Ignore non-output constraints. + } + + assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); + std::string C = InterpretASMConstraint(*I); + if (C.empty()) continue; + + if (!IsFirst) { + Out << ", "; + IsFirst = false; + } + + // Unpack the dest. + Value *DestVal; + int DestValNo = -1; + + if (ValueCount < ResultVals.size()) { + DestVal = ResultVals[ValueCount].first; + DestValNo = ResultVals[ValueCount].second; + } else + DestVal = CI.getArgOperand(ValueCount-ResultVals.size()); + + if (I->isEarlyClobber) + C = "&"+C; + + Out << "\"=" << C << "\"(" << GetValueName(DestVal); + if (DestValNo != -1) + Out << ".field" << DestValNo; // Multiple retvals. + Out << ")"; + ++ValueCount; + } + + + // Convert over all the input constraints. + Out << "\n :"; + IsFirst = true; + ValueCount = 0; + for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), + E = Constraints.end(); I != E; ++I) { + if (I->Type != InlineAsm::isInput) { + ++ValueCount; + continue; // Ignore non-input constraints. + } + + assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); + std::string C = InterpretASMConstraint(*I); + if (C.empty()) continue; + + if (!IsFirst) { + Out << ", "; + IsFirst = false; + } + + assert(ValueCount >= ResultVals.size() && "Input can't refer to result"); + Value *SrcVal = CI.getArgOperand(ValueCount-ResultVals.size()); + + Out << "\"" << C << "\"("; + if (!I->isIndirect) + writeOperand(SrcVal); + else + writeOperandDeref(SrcVal); + Out << ")"; + } + + // Convert over the clobber constraints. + IsFirst = true; + for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), + E = Constraints.end(); I != E; ++I) { + if (I->Type != InlineAsm::isClobber) + continue; // Ignore non-input constraints. + + assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); + std::string C = InterpretASMConstraint(*I); + if (C.empty()) continue; + + if (!IsFirst) { + Out << ", "; + IsFirst = false; + } + + Out << '\"' << C << '"'; + } + + Out << ")"; +} + +void GenWriter::visitAllocaInst(AllocaInst &I) { + Out << '('; + printType(Out, I.getType()); + Out << ") alloca(sizeof("; + printType(Out, I.getType()->getElementType()); + Out << ')'; + if (I.isArrayAllocation()) { + Out << " * " ; + writeOperand(I.getOperand(0)); + } + Out << ')'; +} + +void GenWriter::printGEPExpression(Value *Ptr, gep_type_iterator I, + gep_type_iterator E, bool Static) { + + // If there are no indices, just print out the pointer. + if (I == E) { + writeOperand(Ptr); + return; + } + + // Find out if the last index is into a vector. If so, we have to print this + // specially. Since vectors can't have elements of indexable type, only the + // last index could possibly be of a vector element. + VectorType *LastIndexIsVector = 0; + { + for (gep_type_iterator TmpI = I; TmpI != E; ++TmpI) + LastIndexIsVector = dyn_cast(*TmpI); + } + + Out << "("; + + // If the last index is into a vector, we can't print it as &a[i][j] because + // we can't index into a vector with j in GCC. Instead, emit this as + // (((float*)&a[i])+j) + if (LastIndexIsVector) { + Out << "(("; + printType(Out, PointerType::getUnqual(LastIndexIsVector->getElementType())); + Out << ")("; + } + + Out << '&'; + + // If the first index is 0 (very typical) we can do a number of + // simplifications to clean up the code. + Value *FirstOp = I.getOperand(); + if (!isa(FirstOp) || !cast(FirstOp)->isNullValue()) { + // First index isn't simple, print it the hard way. + writeOperand(Ptr); + } else { + ++I; // Skip the zero index. + + // Okay, emit the first operand. If Ptr is something that is already address + // exposed, like a global, avoid emitting (&foo)[0], just emit foo instead. + if (isAddressExposed(Ptr)) { + writeOperandInternal(Ptr, Static); + } else if (I != E && (*I)->isStructTy()) { + // If we didn't already emit the first operand, see if we can print it as + // P->f instead of "P[0].f" + writeOperand(Ptr); + Out << "->field" << cast(I.getOperand())->getZExtValue(); + ++I; // eat the struct index as well. + } else { + // Instead of emitting P[0][1], emit (*P)[1], which is more idiomatic. + Out << "(*"; + writeOperand(Ptr); + Out << ")"; + } + } + + for (; I != E; ++I) { + if ((*I)->isStructTy()) { + Out << ".field" << cast(I.getOperand())->getZExtValue(); + } else if ((*I)->isArrayTy()) { + Out << ".array["; + writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); + Out << ']'; + } else if (!(*I)->isVectorTy()) { + Out << '['; + writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); + Out << ']'; + } else { + // If the last index is into a vector, then print it out as "+j)". This + // works with the 'LastIndexIsVector' code above. + if (isa(I.getOperand()) && + cast(I.getOperand())->isNullValue()) { + Out << "))"; // avoid "+0". + } else { + Out << ")+("; + writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); + Out << "))"; + } + } + } + Out << ")"; +} + +void GenWriter::writeMemoryAccess(Value *Operand, Type *OperandType, + bool IsVolatile, unsigned Alignment) { + + bool IsUnaligned = Alignment && + Alignment < TD->getABITypeAlignment(OperandType); + + if (!IsUnaligned) + Out << '*'; + if (IsVolatile || IsUnaligned) { + Out << "(("; + if (IsUnaligned) + Out << "struct __attribute__ ((packed, aligned(" << Alignment << "))) {"; + printType(Out, OperandType, false, IsUnaligned ? "data" : "volatile*"); + if (IsUnaligned) { + Out << "; } "; + if (IsVolatile) Out << "volatile "; + Out << "*"; + } + Out << ")"; + } + + writeOperand(Operand); + + if (IsVolatile || IsUnaligned) { + Out << ')'; + if (IsUnaligned) + Out << "->data"; + } +} + +void GenWriter::visitLoadInst(LoadInst &I) { + writeMemoryAccess(I.getOperand(0), I.getType(), I.isVolatile(), + I.getAlignment()); + +} + +void GenWriter::visitStoreInst(StoreInst &I) { + writeMemoryAccess(I.getPointerOperand(), I.getOperand(0)->getType(), + I.isVolatile(), I.getAlignment()); + Out << " = "; + Value *Operand = I.getOperand(0); + Constant *BitMask = 0; + if (IntegerType* ITy = dyn_cast(Operand->getType())) + if (!ITy->isPowerOf2ByteWidth()) + // We have a bit width that doesn't match an even power-of-2 byte + // size. Consequently we must & the value with the type's bit mask + BitMask = ConstantInt::get(ITy, ITy->getBitMask()); + if (BitMask) + Out << "(("; + writeOperand(Operand); + if (BitMask) { + Out << ") & "; + printConstant(BitMask, false); + Out << ")"; + } +} + +void GenWriter::visitGetElementPtrInst(GetElementPtrInst &I) { + printGEPExpression(I.getPointerOperand(), gep_type_begin(I), + gep_type_end(I), false); +} + +void GenWriter::visitVAArgInst(VAArgInst &I) { + Out << "va_arg(*(va_list*)"; + writeOperand(I.getOperand(0)); + Out << ", "; + printType(Out, I.getType()); + Out << ");\n "; +} + +void GenWriter::visitInsertElementInst(InsertElementInst &I) { + Type *EltTy = I.getType()->getElementType(); + writeOperand(I.getOperand(0)); + Out << ";\n "; + Out << "(("; + printType(Out, PointerType::getUnqual(EltTy)); + Out << ")(&" << GetValueName(&I) << "))["; + writeOperand(I.getOperand(2)); + Out << "] = ("; + writeOperand(I.getOperand(1)); + Out << ")"; +} + +void GenWriter::visitExtractElementInst(ExtractElementInst &I) { + // We know that our operand is not inlined. + Out << "(("; + Type *EltTy = + cast(I.getOperand(0)->getType())->getElementType(); + printType(Out, PointerType::getUnqual(EltTy)); + Out << ")(&" << GetValueName(I.getOperand(0)) << "))["; + writeOperand(I.getOperand(1)); + Out << "]"; +} + +void GenWriter::visitShuffleVectorInst(ShuffleVectorInst &SVI) { + Out << "("; + printType(Out, SVI.getType()); + Out << "){ "; + VectorType *VT = SVI.getType(); + unsigned NumElts = VT->getNumElements(); + Type *EltTy = VT->getElementType(); + + for (unsigned i = 0; i != NumElts; ++i) { + if (i) Out << ", "; + int SrcVal = SVI.getMaskValue(i); + if ((unsigned)SrcVal >= NumElts*2) { + Out << " 0/*undef*/ "; + } else { + Value *Op = SVI.getOperand((unsigned)SrcVal >= NumElts); + if (isa(Op)) { + // Do an extractelement of this value from the appropriate input. + Out << "(("; + printType(Out, PointerType::getUnqual(EltTy)); + Out << ")(&" << GetValueName(Op) + << "))[" << (SrcVal & (NumElts-1)) << "]"; + } else if (isa(Op) || isa(Op)) { + Out << "0"; + } else { + printConstant(cast(Op)->getOperand(SrcVal & + (NumElts-1)), + false); + } + } + } + Out << "}"; +} + +void GenWriter::visitInsertValueInst(InsertValueInst &IVI) { + // Start by copying the entire aggregate value into the result variable. + writeOperand(IVI.getOperand(0)); + Out << ";\n "; + + // Then do the insert to update the field. + Out << GetValueName(&IVI); + for (const unsigned *b = IVI.idx_begin(), *i = b, *e = IVI.idx_end(); + i != e; ++i) { + Type *IndexedTy = + ExtractValueInst::getIndexedType(IVI.getOperand(0)->getType(), + makeArrayRef(b, i+1)); + if (IndexedTy->isArrayTy()) + Out << ".array[" << *i << "]"; + else + Out << ".field" << *i; + } + Out << " = "; + writeOperand(IVI.getOperand(1)); +} + +void GenWriter::visitExtractValueInst(ExtractValueInst &EVI) { + Out << "("; + if (isa(EVI.getOperand(0))) { + Out << "("; + printType(Out, EVI.getType()); + Out << ") 0/*UNDEF*/"; + } else { + Out << GetValueName(EVI.getOperand(0)); + for (const unsigned *b = EVI.idx_begin(), *i = b, *e = EVI.idx_end(); + i != e; ++i) { + Type *IndexedTy = + ExtractValueInst::getIndexedType(EVI.getOperand(0)->getType(), + makeArrayRef(b, i+1)); + if (IndexedTy->isArrayTy()) + Out << ".array[" << *i << "]"; + else + Out << ".field" << *i; + } + } + Out << ")"; +} + +//===----------------------------------------------------------------------===// +// External Interface declaration +//===----------------------------------------------------------------------===// + +bool GenTargetMachine::addPassesToEmitFile(PassManagerBase &PM, + formatted_raw_ostream &o, + CodeGenFileType FileType, + CodeGenOpt::Level OptLevel, + bool DisableVerify) { + if (FileType != TargetMachine::CGFT_AssemblyFile) return true; + + PM.add(createGCLoweringPass()); + PM.add(createLowerInvokePass()); + PM.add(createCFGSimplificationPass()); // clean up after lower invoke. + PM.add(new GenWriter(o)); + PM.add(createGCInfoDeleter()); + return false; +} + diff --git a/backend/src/llvm/GenTargetMachine.h b/backend/src/llvm/GenTargetMachine.h new file mode 100644 index 0000000..767f8bd --- /dev/null +++ b/backend/src/llvm/GenTargetMachine.h @@ -0,0 +1,61 @@ +/* + * Copyright © 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Benjamin Segovia + */ + +//===-- GenTargetMachine.h - TargetMachine for the C backend ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the TargetMachine that is used by the C backend. +// +//===----------------------------------------------------------------------===// + +#ifndef CTARGETMACHINE_H +#define CTARGETMACHINE_H + +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" + +namespace llvm { + +struct GenTargetMachine : public TargetMachine { + GenTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM) + : TargetMachine(T, TT, CPU, FS) {} + + virtual bool addPassesToEmitFile(PassManagerBase &PM, + formatted_raw_ostream &Out, + CodeGenFileType FileType, + CodeGenOpt::Level OptLevel, + bool DisableVerify); + + virtual const TargetData *getTargetData() const { return 0; } +}; + +extern Target TheGenBackendTarget; + +} // End llvm namespace + + +#endif diff --git a/backend/src/llvm/Makefile b/backend/src/llvm/Makefile new file mode 100644 index 0000000..621948a --- /dev/null +++ b/backend/src/llvm/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/CBackend/Makefile ------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMCBackend +DIRS = TargetInfo + +include $(LEVEL)/Makefile.common + +CompileCommonOpts += -Wno-format diff --git a/backend/src/llvm/TargetInfo/.GenBackendTargetInfo.cpp.swp b/backend/src/llvm/TargetInfo/.GenBackendTargetInfo.cpp.swp new file mode 100644 index 0000000000000000000000000000000000000000..5ac42cbdba8d0b130dc7b902b771d26d497bbc71 GIT binary patch literal 12288 zcmeI2&u-H|5XPsRDHM=6Pu)u@k+=|~N-g1lRZvhuC6ZRXfN<^(Jmss=#9f;NeGacl2Nt z-rNM}q|}Rt${(i|jcHw3ZEh^8dp0d}Qxmv7(&dgH9Fh+6=O`Ku+_rCeWb3*cySGT+ zn52KaSqYM4Q3uHh0U>Zafn}&(xtxDT*PKh)XlEc$6Rngn$qb0zyCt2mv7=1cZPP5CTF#2%JCyehBdSG{C)O z-aP;RKmGmx;Vi&=mSsI+l~`ZT0DNJ+W4&d)V5O|vtgEal>l|x^^@-Pe&3eUp$-2+V zdz?Tga6v#ym@ex#nzti!qK zmDcg;2w((=cd4gRo;@)?U%QS6rFQ?fDVNY;AGO1Q7sJ9%?W}LZ-*p}vuE)I*VA2oA zZtShCIUTnFvQ+6FYJWg!;s=!1Zo`_=L6n7rPVVGxWl0hnTR6HWr!hyBzB60cjKeIV zUlV+o$v&EX&{sOog6r05wemk1ypZeig8agU3P`6^!4?rV>fX+s)=s5;(8g|TFeK}% zD6NbO+kKT{S4D&zL%tlNI+>*qGaZsa+b7)9YDgwk_6XxH)}u)2n2UE4zMNK^nShF> zIA<{I`~!ksJV>~WLB1B_bDu1*nJK2`4A7fvjmPr$1Qz#LA0!bCNL$~kSmRIhCJep- Dng|Hd literal 0 HcmV?d00001 diff --git a/backend/src/llvm/TargetInfo/CMakeLists.txt b/backend/src/llvm/TargetInfo/CMakeLists.txt new file mode 100644 index 0000000..9ce8817 --- /dev/null +++ b/backend/src/llvm/TargetInfo/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMGenBackendInfo + GenBackendTargetInfo.cpp + ) + +add_llvm_library_dependencies(LLVMGenBackendInfo + LLVMMC + LLVMSupport + LLVMTarget) diff --git a/backend/src/llvm/TargetInfo/GenBackendTargetInfo.cpp b/backend/src/llvm/TargetInfo/GenBackendTargetInfo.cpp new file mode 100644 index 0000000..dec6a46 --- /dev/null +++ b/backend/src/llvm/TargetInfo/GenBackendTargetInfo.cpp @@ -0,0 +1,41 @@ +/* + * Copyright © 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Benjamin Segovia + */ + +//===-- CBackendTargetInfo.cpp - CBackend Target Implementation -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "GenTargetMachine.h" +#include "llvm/Module.h" +#include "llvm/Support/TargetRegistry.h" +using namespace llvm; + +Target llvm::TheGenBackendTarget; + +extern "C" void LLVMInitializeGenBackendTargetInfo() { + RegisterTarget<> X(TheGenBackendTarget, "gen", "Gen backend"); +} + +extern "C" void LLVMInitializeGenBackendTargetMC() {} + diff --git a/backend/src/llvm/TargetInfo/Makefile b/backend/src/llvm/TargetInfo/Makefile new file mode 100644 index 0000000..d4d5e15 --- /dev/null +++ b/backend/src/llvm/TargetInfo/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/CBackend/TargetInfo/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMCBackendInfo + +# Hack: we need to include 'main' target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common -- 2.7.4