[runtime] Reenable Frak TLS on OSX
[mono-project.git] / mono / utils / mono-compiler.h
blobd06a2143a02e6394146385c1a9bc377978701a50
1 #ifndef __UTILS_MONO_COMPILER_H__
2 #define __UTILS_MONO_COMPILER_H__
4 /*
5 * This file includes macros used in the runtime to encapsulate different
6 * compiler behaviours.
7 */
8 #include <config.h>
10 #ifdef __GNUC__
11 #define MONO_ATTR_USED __attribute__ ((used))
12 #else
13 #define MONO_ATTR_USED
14 #endif
16 #ifdef HAVE_KW_THREAD
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;
24 #if HAVE_TLS_MODEL_ATTR
26 #if defined(__PIC__) && !defined(PIC)
28 * Must be compiling -fPIE, for executables. Build PIC
29 * but with initial-exec.
30 * http://bugs.gentoo.org/show_bug.cgi?id=165547
32 #define PIC
33 #define PIC_INITIAL_EXEC
34 #endif
36 /*
37 * Define this if you want a faster libmono, which cannot be loaded dynamically as a
38 * module.
40 //#define PIC_INITIAL_EXEC
42 #if defined(PIC)
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.
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
61 #else
63 #define MONO_TLS_FAST __attribute__((tls_model("local-exec")))
65 #endif
67 #else
68 #define MONO_TLS_FAST
69 #endif
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
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
113 #else
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.
121 For now we will disable this. */
122 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
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
174 #if defined(PIC) && !defined(PIC_INITIAL_EXEC)
176 * The above definitions do not seem to work if libmono is loaded dynamically as a module.
177 * See bug #78767.
179 #undef MONO_THREAD_VAR_OFFSET
180 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
181 #endif
183 #elif defined(TARGET_MACH) && (defined(__i386__) || defined(__x86_64__))
185 #define MONO_HAVE_FAST_TLS
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;
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 #else /* no HAVE_KW_THREAD */
199 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
201 /*Macros to facilitate user code*/
202 #define MONO_FAST_TLS_INIT(x)
203 #endif
205 #if defined(MONO_HAVE_FAST_TLS) && !defined(MONO_FAST_TLS_ADDR)
206 #define MONO_FAST_TLS_ADDR(x) (&(x))
207 #endif
210 /* Deal with Microsoft C compiler differences */
211 #ifdef _MSC_VER
213 #include <math.h>
215 #if _MSC_VER < 1800 /* VS 2013 */
216 #define strtoull _strtoui64
217 #endif
219 #include <float.h>
220 #define trunc(x) (((x) < 0) ? ceil((x)) : floor((x)))
221 #if _MSC_VER < 1800 /* VS 2013 */
222 #define isnan(x) _isnan(x)
223 #define isinf(x) (_isnan(x) ? 0 : (_fpclass(x) == _FPCLASS_NINF) ? -1 : (_fpclass(x) == _FPCLASS_PINF) ? 1 : 0)
224 #define isnormal(x) _finite(x)
225 #endif
227 #define popen _popen
228 #define pclose _pclose
230 #include <direct.h>
231 #define mkdir(x) _mkdir(x)
233 /* GCC specific functions aren't available */
234 #define __builtin_return_address(x) NULL
236 #define __func__ __FUNCTION__
238 #include <BaseTsd.h>
239 typedef SSIZE_T ssize_t;
242 * SSIZE_MAX is not defined in MSVC, so define it here.
244 * These values come from MinGW64, and are public domain.
247 #ifndef SSIZE_MAX
248 #ifdef _WIN64
249 #define SSIZE_MAX _I64_MAX
250 #else
251 #define SSIZE_MAX INT_MAX
252 #endif
253 #endif
255 #endif /* _MSC_VER */
257 #if !defined(_MSC_VER) && !defined(PLATFORM_SOLARIS) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MONOTOUCH) && HAVE_VISIBILITY_HIDDEN
258 #if MONO_LLVM_LOADED
259 #define MONO_LLVM_INTERNAL MONO_API
260 #else
261 #define MONO_LLVM_INTERNAL
262 #endif
263 #else
264 #define MONO_LLVM_INTERNAL
265 #endif
267 #if HAVE_DEPRECATED
268 #define MONO_DEPRECATED __attribute__ ((deprecated))
269 #else
270 #define MONO_DEPRECATED
271 #endif
273 #ifdef __GNUC__
274 #define MONO_ALWAYS_INLINE __attribute__((always_inline))
275 #elif defined(_MSC_VER)
276 #define MONO_ALWAYS_INLINE __forceinline
277 #else
278 #define MONO_ALWAYS_INLINE
279 #endif
281 #ifdef __GNUC__
282 #define MONO_NEVER_INLINE __attribute__((noinline))
283 #elif defined(_MSC_VER)
284 #define MONO_NEVER_INLINE __declspec(noinline)
285 #else
286 #define MONO_NEVER_INLINE
287 #endif
289 #ifdef __GNUC__
290 #define MONO_COLD __attribute__((cold))
291 #else
292 #define MONO_COLD
293 #endif
295 #endif /* __UTILS_MONO_COMPILER_H__*/