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