a533a9f01e33867044ce77558d92992f1bfac588
[mono.git] / mono / utils / mono-compiler.h
1 #ifndef __UTILS_MONO_COMPILER_H__
2 #define __UTILS_MONO_COMPILER_H__
3
4 /*
5  * This file includes macros used in the runtime to encapsulate different
6  * compiler behaviours.
7  */
8 #include <config.h>
9
10 #ifdef HAVE_KW_THREAD
11
12 #define MONO_HAVE_FAST_TLS
13 #define MONO_FAST_TLS_SET(x,y) x = y
14 #define MONO_FAST_TLS_GET(x) x
15 #define MONO_FAST_TLS_INIT(x)
16 #define MONO_FAST_TLS_DECLARE(x) static __thread gpointer x MONO_TLS_FAST;
17
18 #if HAVE_TLS_MODEL_ATTR
19
20 #if defined(__PIC__) && !defined(PIC)
21 /*
22  * Must be compiling -fPIE, for executables.  Build PIC
23  * but with initial-exec.
24  * http://bugs.gentoo.org/show_bug.cgi?id=165547
25  */
26 #define PIC
27 #define PIC_INITIAL_EXEC
28 #endif
29
30 /* 
31  * Define this if you want a faster libmono, which cannot be loaded dynamically as a 
32  * module.
33  */
34 //#define PIC_INITIAL_EXEC
35
36 #if defined(PIC)
37
38 #ifdef PIC_INITIAL_EXEC
39 #define MONO_TLS_FAST __attribute__((tls_model("initial-exec")))
40 #else
41 #if defined (__powerpc__)
42 /* local dynamic requires a call to __tls_get_addr to look up the
43    TLS block address via the Dynamic Thread Vector. In this case Thread
44    Pointer relative offsets can't be used as this modules TLS was
45    allocated separately (none contiguoiusly) from the initial TLS
46    block.
47
48    For now we will disable this. */
49 #define MONO_TLS_FAST
50 #else
51 #define MONO_TLS_FAST __attribute__((tls_model("local-dynamic")))
52 #endif
53 #endif
54
55 #else
56
57 #define MONO_TLS_FAST __attribute__((tls_model("local-exec")))
58
59 #endif
60
61 #else
62 #define MONO_TLS_FAST 
63 #endif
64
65 #if defined(__GNUC__) && defined(__i386__)
66 #if defined(PIC)
67 #define MONO_THREAD_VAR_OFFSET(var,offset) do { int tmp; __asm ("call 1f; 1: popl %0; addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %0; movl " #var "@gotntpoff(%0), %1" : "=r" (tmp), "=r" (offset)); } while (0)
68 #else
69 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("movl $" #var "@ntpoff, %0" : "=r" (offset))
70 #endif
71 #elif defined(__x86_64__)
72 #if defined(PIC)
73 // This only works if libmono is linked into the application
74 #define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;  __asm ("movq " #var "@GOTTPOFF(%%rip), %0" : "=r" (foo)); offset = foo; } while (0)
75 #else
76 #define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;  __asm ("movq $" #var "@TPOFF, %0" : "=r" (foo)); offset = foo; } while (0)
77 #endif
78 #elif defined(__ia64__) && !defined(__INTEL_COMPILER)
79 #if defined(PIC)
80 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @ltoff(@tprel(" #var "#)), gp ;; ld8 %0 = [%0]\n" : "=r" (offset))
81 #else
82 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @tprel(" #var "#), r0 ;;\n" : "=r" (offset))
83 #endif
84 #elif defined(__arm__) && defined(__ARM_EABI__) && !defined(PIC)
85 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("     ldr     %0, 1f; b 2f; 1: .word " #var "(tpoff); 2:" : "=r" (offset))
86 #elif defined(__mono_ppc__) && defined(__GNUC__)
87 #if defined(PIC)
88 #ifdef PIC_INITIAL_EXEC
89
90 #if defined(__mono_ppc64__)
91 #define MONO_THREAD_VAR_OFFSET(var,offset) \
92         do { long off; \
93         __asm ( "ld     %0," #var "@got@tprel(2)\n" \
94         : "=r" (off)); \
95         (offset) = off; } while (0)
96 #else
97 /* must be powerpc32 */
98 #define MONO_THREAD_VAR_OFFSET(var,offset) \
99         __asm ( "lwz    %0," #var "@got@tprel(30)\n" \
100         : "=r" (offset))
101 #endif
102
103 #else
104
105 /* local dynamic requires a call to __tls_get_addr to look up the
106    TLS block address via the Dynamic Thread Vector. In this case Thread
107    Pointer relative offsets can't be used as this modules TLS was
108    allocated separately (none contiguoiusly) from the initial TLS
109    block.
110
111    For now we will disable this. */
112 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
113
114 #endif
115 #else
116 /* Must be local-exec TLS */
117 #define MONO_THREAD_VAR_OFFSET(var,offset) \
118         __asm ( "lis    %0," #var "@tprel@ha\n" \
119                 "addi   %0,%0, " #var "@tprel@l\n" \
120         : "=r" (offset))
121 #endif
122 #elif defined(__s390x__)
123 # if defined(PIC)
124 // This only works if libmono is linked into the application
125 #  define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                  \
126                                                 __asm__ ("basr  %%r1,0\n\t"                     \
127                                                          "j     0f\n\t"                         \
128                                                          ".quad " #var "@TLSGD\n\t"             \
129                                                          "0:\n\t"                               \
130                                                          "lg    %%r2,4(%%r1)\n\t"               \
131                                                          "brasl %%r14,__tls_get_offset@PLT:tls_gdcall:"#var"\n\t" \
132                                                          "lgr   %0,%%r2\n\t"                    \
133                                                         : "=r" (foo) :                          \
134                                                         : "1", "2", "14", "cc");                \
135                                                 offset = foo; } while (0)
136 # else
137 #  define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                  \
138                                                 __asm__ ("basr  %%r1,0\n\t"                     \
139                                                          "j     0f\n\t"                         \
140                                                          ".quad " #var "@NTPOFF\n"              \
141                                                          "0:\n\t"                               \
142                                                          "lg    %0,4(%%r1)\n\t"                 \
143                                                         : "=r" (foo) : : "1");                  \
144                                                 offset = foo; } while (0)
145 # endif
146
147 #else
148 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
149 #endif
150
151 #if defined(PIC) && !defined(PIC_INITIAL_EXEC)
152 /* 
153  * The above definitions do not seem to work if libmono is loaded dynamically as a module.
154  * See bug #78767.
155  */
156 #undef MONO_THREAD_VAR_OFFSET
157 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
158 #endif
159
160 #elif defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
161
162 #define MONO_HAVE_FAST_TLS
163 #define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
164 #define MONO_FAST_TLS_GET(x) pthread_getspecific(x)
165 #define MONO_FAST_TLS_ADDR(x) (mono_mach_get_tls_address_from_thread (pthread_self (), x))
166 #define MONO_FAST_TLS_INIT(x) pthread_key_create(&x, NULL)
167 #define MONO_FAST_TLS_DECLARE(x) static pthread_key_t x;
168
169 #define MONO_THREAD_VAR_OFFSET(x,y) ({  \
170         typeof(x) _x = (x);                     \
171         pthread_key_t _y;       \
172         (void) (&_x == &_y);            \
173         y = (gint32) x; })
174 #else /* no HAVE_KW_THREAD */
175
176 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
177
178 /*Macros to facilitate user code*/
179 #define MONO_FAST_TLS_INIT(x)
180 #endif
181
182 #if defined(MONO_HAVE_FAST_TLS) && !defined(MONO_FAST_TLS_ADDR)
183 #define MONO_FAST_TLS_ADDR(x) (&(x))
184 #endif
185
186
187 /* Deal with Microsoft C compiler differences */
188 #ifdef _MSC_VER
189
190 #include <math.h>
191
192 #if _MSC_VER < 1800 /* VS 2013 */
193 #define strtoull _strtoui64
194 #endif
195
196 #include <float.h>
197 #define isnan(x)        _isnan(x)
198 #define trunc(x)        (((x) < 0) ? ceil((x)) : floor((x)))
199 #define isinf(x)        (_isnan(x) ? 0 : (_fpclass(x) == _FPCLASS_NINF) ? -1 : (_fpclass(x) == _FPCLASS_PINF) ? 1 : 0)
200 #define isnormal(x)     _finite(x)
201
202 #define popen           _popen
203 #define pclose          _pclose
204
205 #include <direct.h>
206 #define mkdir(x)        _mkdir(x)
207
208 /* GCC specific functions aren't available */
209 #define __builtin_return_address(x)     NULL
210
211 #define __func__ __FUNCTION__
212
213 #endif /* _MSC_VER */
214
215 #if !defined(_MSC_VER) && !defined(PLATFORM_SOLARIS) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MONOTOUCH) && HAVE_VISIBILITY_HIDDEN
216 #define MONO_INTERNAL __attribute__ ((visibility ("hidden")))
217 #if MONO_LLVM_LOADED
218 #define MONO_LLVM_INTERNAL 
219 #else
220 #define MONO_LLVM_INTERNAL MONO_INTERNAL
221 #endif
222 #else
223 #define MONO_INTERNAL 
224 #define MONO_LLVM_INTERNAL 
225 #endif
226
227 #if HAVE_DEPRECATED
228 #define MONO_DEPRECATED __attribute__ ((deprecated))
229 #else
230 #define MONO_DEPRECATED 
231 #endif
232
233 #ifdef __GNUC__
234 #define MONO_ALWAYS_INLINE __attribute__((always_inline))
235 #elif defined(_MSC_VER)
236 #define MONO_ALWAYS_INLINE __forceinline
237 #else
238 #define MONO_ALWAYS_INLINE
239 #endif
240
241 #endif /* __UTILS_MONO_COMPILER_H__*/
242