Merge pull request #2769 from lewurm/jit-cfg-dump
[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 /*
11  * When embedding, you have to define MONO_ZERO_LEN_ARRAY before including any
12  * other Mono header file if you use a different compiler from the one used to
13  * build Mono.
14  */
15 #ifndef MONO_ZERO_LEN_ARRAY
16 #ifdef __GNUC__
17 #define MONO_ZERO_LEN_ARRAY 0
18 #else
19 #define MONO_ZERO_LEN_ARRAY 1
20 #endif
21 #endif
22
23 #ifdef __GNUC__
24 #define MONO_ATTR_USED __attribute__ ((used))
25 #else
26 #define MONO_ATTR_USED
27 #endif
28
29 #ifdef HAVE_KW_THREAD
30
31 #define MONO_HAVE_FAST_TLS
32 #define MONO_FAST_TLS_SET(x,y) x = y
33 #define MONO_FAST_TLS_GET(x) x
34 #define MONO_FAST_TLS_INIT(x)
35 #define MONO_FAST_TLS_DECLARE(x) static __thread gpointer x MONO_TLS_FAST MONO_ATTR_USED;
36
37 #if HAVE_TLS_MODEL_ATTR
38
39 #if defined(__PIC__) && !defined(PIC)
40 /*
41  * Must be compiling -fPIE, for executables.  Build PIC
42  * but with initial-exec.
43  * http://bugs.gentoo.org/show_bug.cgi?id=165547
44  */
45 #define PIC
46 #define PIC_INITIAL_EXEC
47 #endif
48
49 /* 
50  * Define this if you want a faster libmono, which cannot be loaded dynamically as a 
51  * module.
52  */
53 //#define PIC_INITIAL_EXEC
54
55 #if defined(PIC)
56
57 #ifdef PIC_INITIAL_EXEC
58 #define MONO_TLS_FAST __attribute__((tls_model("initial-exec")))
59 #else
60 #if defined (__powerpc__)
61 /* local dynamic requires a call to __tls_get_addr to look up the
62    TLS block address via the Dynamic Thread Vector. In this case Thread
63    Pointer relative offsets can't be used as this modules TLS was
64    allocated separately (none contiguoiusly) from the initial TLS
65    block.
66
67    For now we will disable this. */
68 #define MONO_TLS_FAST
69 #else
70 #define MONO_TLS_FAST __attribute__((tls_model("local-dynamic")))
71 #endif
72 #endif
73
74 #else
75
76 #define MONO_TLS_FAST __attribute__((tls_model("local-exec")))
77
78 #endif
79
80 #else
81 #define MONO_TLS_FAST 
82 #endif
83
84 #if defined(__GNUC__) && defined(__i386__)
85 #if defined(PIC)
86 #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)
87 #else
88 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("movl $" #var "@ntpoff, %0" : "=r" (offset))
89 #endif
90 #elif defined(__x86_64__)
91 #if defined(PIC)
92 // This only works if libmono is linked into the application
93 #define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;  __asm ("movq " #var "@GOTTPOFF(%%rip), %0" : "=r" (foo)); offset = foo; } while (0)
94 #else
95 #define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;  __asm ("movq $" #var "@TPOFF, %0" : "=r" (foo)); offset = foo; } while (0)
96 #endif
97 #elif defined(__ia64__) && !defined(__INTEL_COMPILER)
98 #if defined(PIC)
99 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @ltoff(@tprel(" #var "#)), gp ;; ld8 %0 = [%0]\n" : "=r" (offset))
100 #else
101 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @tprel(" #var "#), r0 ;;\n" : "=r" (offset))
102 #endif
103 #elif defined(__arm__) && defined(__ARM_EABI__) && !defined(PIC)
104 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("     ldr     %0, 1f; b 2f; 1: .word " #var "(tpoff); 2:" : "=r" (offset))
105 #elif defined(__aarch64__) && !defined(PIC)
106 #define MONO_THREAD_VAR_OFFSET(var,offset) \
107         __asm ( "mov %0, #0\n add %0, %0, #:tprel_hi12:" #var "\n add %0, %0, #:tprel_lo12_nc:" #var "\n" \
108                         : "=r" (offset))
109 #elif defined(__mono_ppc__) && defined(__GNUC__)
110 #if defined(PIC)
111 #ifdef PIC_INITIAL_EXEC
112
113 #if defined(__mono_ppc64__)
114 #define MONO_THREAD_VAR_OFFSET(var,offset) \
115         do { long off; \
116         __asm ( "ld     %0," #var "@got@tprel(2)\n" \
117         : "=r" (off)); \
118         (offset) = off; } while (0)
119 #else
120 /* must be powerpc32 */
121 #define MONO_THREAD_VAR_OFFSET(var,offset) \
122         __asm ( "lwz    %0," #var "@got@tprel(30)\n" \
123         : "=r" (offset))
124 #endif
125
126 #else
127
128 /* local dynamic requires a call to __tls_get_addr to look up the
129    TLS block address via the Dynamic Thread Vector. In this case Thread
130    Pointer relative offsets can't be used as this modules TLS was
131    allocated separately (none contiguoiusly) from the initial TLS
132    block.
133
134    For now we will disable this. */
135 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
136
137 #endif
138 #else
139 /* Must be local-exec TLS */
140 #define MONO_THREAD_VAR_OFFSET(var,offset) \
141         __asm ( "lis    %0," #var "@tprel@ha\n" \
142                 "addi   %0,%0, " #var "@tprel@l\n" \
143         : "=r" (offset))
144 #endif
145 #elif defined(__s390x__)
146 # if defined(__PIC__)
147 #  if !defined(__PIE__)
148 // This only works if libmono is linked into the application
149 #   define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                 \
150                                                 __asm__ ("basr  %%r1,0\n\t"                     \
151                                                          "j     0f\n\t"                         \
152                                                          ".quad " #var "@TLSGD\n"               \
153                                                          "0:\n\t"                               \
154                                                          "lg    %%r2,4(%%r1)\n\t"               \
155                                                          "brasl %%r14,__tls_get_offset@PLT:tls_gdcall:"#var"\n\t" \
156                                                          "lgr   %0,%%r2\n\t"                    \
157                                                         : "=r" (foo) :                          \
158                                                         : "1", "2", "14", "cc");                \
159                                                 offset = foo; } while (0)
160 #  elif __PIE__ == 1
161 #   define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                         \
162                                                 __asm__ ("lg    %0," #var "@GOTNTPOFF(%%r12)\n\t"       \
163                                                          : "=r" (foo));                                 \
164                                                 offset = foo; } while (0)
165 #  elif __PIE__ == 2
166 #   define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                 \
167                                                 __asm__ ("larl  %%r1," #var "@INDNTPOFF\n\t"    \
168                                                          "lg    %0,0(%%r1)\n\t"                 \
169                                                          : "=r" (foo) :                         \
170                                                          : "1", "cc");                          \
171                                                 offset = foo; } while (0)
172 #  endif
173 # else
174 #  define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                          \
175                                                 __asm__ ("basr  %%r1,0\n\t"             \
176                                                          "j     0f\n\t"                 \
177                                                          ".quad " #var "@NTPOFF\n"      \
178                                                          "0:\n\t"                       \
179                                                          "lg    %0,4(%%r1)\n\t"         \
180                                                         : "=r" (foo) : : "1");          \
181                                                 offset = foo; } while (0)
182 # endif
183 #else
184 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
185 #endif
186
187 #if defined(PIC) && !defined(PIC_INITIAL_EXEC)
188 /* 
189  * The above definitions do not seem to work if libmono is loaded dynamically as a module.
190  * See bug #78767.
191  */
192 #undef MONO_THREAD_VAR_OFFSET
193 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
194 #endif
195
196 #elif !defined(MONO_CROSS_COMPILE) && defined(PLATFORM_MACOSX) && (defined(__i386__) || defined(__x86_64__))
197
198 #define MONO_HAVE_FAST_TLS 1
199 #define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
200 #define MONO_FAST_TLS_GET(x) pthread_getspecific(x)
201 #define MONO_FAST_TLS_ADDR(x) (mono_mach_get_tls_address_from_thread (pthread_self (), x))
202 #define MONO_FAST_TLS_INIT(x) pthread_key_create(&x, NULL)
203 #define MONO_FAST_TLS_DECLARE(x) static pthread_key_t x;
204
205 #define MONO_THREAD_VAR_OFFSET(x,y) ({  \
206         __typeof__(x) _x = (x);                 \
207         pthread_key_t _y;       \
208         (void) (&_x == &_y);            \
209         y = (gint32) x; })
210
211 #elif !defined(MONO_CROSS_COMPILE) && (defined(PLATFORM_ANDROID) || defined(TARGET_IOS)) && defined(TARGET_ARM)
212
213 #define MONO_HAVE_FAST_TLS
214 #define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
215 #define MONO_FAST_TLS_GET(x) pthread_getspecific(x)
216 #define MONO_FAST_TLS_INIT(x) pthread_key_create(&x, NULL)
217 #define MONO_FAST_TLS_DECLARE(x) static pthread_key_t x;
218
219 #define MONO_THREAD_VAR_OFFSET(var, offset) do { offset = (int)var; } while (0)
220
221 #else /* no HAVE_KW_THREAD */
222
223 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
224
225 /*Macros to facilitate user code*/
226 #define MONO_FAST_TLS_INIT(x)
227 #endif
228
229 #if defined(MONO_HAVE_FAST_TLS) && !defined(MONO_FAST_TLS_ADDR)
230 #define MONO_FAST_TLS_ADDR(x) (&(x))
231 #endif
232
233
234 /* Deal with Microsoft C compiler differences */
235 #ifdef _MSC_VER
236
237 #include <math.h>
238
239 #if _MSC_VER < 1800 /* VS 2013 */
240 #define strtoull _strtoui64
241 #endif
242
243 #include <float.h>
244 #define trunc(x)        (((x) < 0) ? ceil((x)) : floor((x)))
245 #if _MSC_VER < 1800 /* VS 2013 */
246 #define isnan(x)        _isnan(x)
247 #define isinf(x)        (_isnan(x) ? 0 : (_fpclass(x) == _FPCLASS_NINF) ? -1 : (_fpclass(x) == _FPCLASS_PINF) ? 1 : 0)
248 #define isnormal(x)     _finite(x)
249 #endif
250
251 #define popen           _popen
252 #define pclose          _pclose
253
254 #include <direct.h>
255 #define mkdir(x)        _mkdir(x)
256
257 /* GCC specific functions aren't available */
258 #define __builtin_return_address(x)     NULL
259
260 #define __func__ __FUNCTION__
261
262 #include <BaseTsd.h>
263 typedef SSIZE_T ssize_t;
264
265 /*
266  * SSIZE_MAX is not defined in MSVC, so define it here.
267  *
268  * These values come from MinGW64, and are public domain.
269  *
270  */
271 #ifndef SSIZE_MAX
272 #ifdef _WIN64
273 #define SSIZE_MAX _I64_MAX
274 #else
275 #define SSIZE_MAX INT_MAX
276 #endif
277 #endif
278
279 #endif /* _MSC_VER */
280
281 #if !defined(_MSC_VER) && !defined(PLATFORM_SOLARIS) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MONOTOUCH) && HAVE_VISIBILITY_HIDDEN
282 #if MONO_LLVM_LOADED
283 #define MONO_LLVM_INTERNAL MONO_API
284 #else
285 #define MONO_LLVM_INTERNAL
286 #endif
287 #else
288 #define MONO_LLVM_INTERNAL 
289 #endif
290
291 #if HAVE_DEPRECATED
292 #define MONO_DEPRECATED __attribute__ ((deprecated))
293 #else
294 #define MONO_DEPRECATED 
295 #endif
296
297 #ifdef __GNUC__
298 #define MONO_ALWAYS_INLINE __attribute__((always_inline))
299 #elif defined(_MSC_VER)
300 #define MONO_ALWAYS_INLINE __forceinline
301 #else
302 #define MONO_ALWAYS_INLINE
303 #endif
304
305 #ifdef __GNUC__
306 #define MONO_NEVER_INLINE __attribute__((noinline))
307 #elif defined(_MSC_VER)
308 #define MONO_NEVER_INLINE __declspec(noinline)
309 #else
310 #define MONO_NEVER_INLINE
311 #endif
312
313 #ifdef __GNUC__
314 #define MONO_COLD __attribute__((cold))
315 #else
316 #define MONO_COLD
317 #endif
318
319 #endif /* __UTILS_MONO_COMPILER_H__*/
320