[runtime]
[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 // This only works if libmono is linked into the application
135 #  define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                  \
136                                                 __asm__ ("basr  %%r1,0\n\t"                     \
137                                                          "j     0f\n\t"                         \
138                                                          ".quad " #var "@TLSGD\n\t"             \
139                                                          "0:\n\t"                               \
140                                                          "lg    %%r2,4(%%r1)\n\t"               \
141                                                          "brasl %%r14,__tls_get_offset@PLT:tls_gdcall:"#var"\n\t" \
142                                                          "lgr   %0,%%r2\n\t"                    \
143                                                         : "=r" (foo) :                          \
144                                                         : "1", "2", "14", "cc");                \
145                                                 offset = foo; } while (0)
146 # else
147 #  define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                  \
148                                                 __asm__ ("basr  %%r1,0\n\t"                     \
149                                                          "j     0f\n\t"                         \
150                                                          ".quad " #var "@NTPOFF\n"              \
151                                                          "0:\n\t"                               \
152                                                          "lg    %0,4(%%r1)\n\t"                 \
153                                                         : "=r" (foo) : : "1");                  \
154                                                 offset = foo; } while (0)
155 # endif
156
157 #else
158 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
159 #endif
160
161 #if defined(PIC) && !defined(PIC_INITIAL_EXEC)
162 /* 
163  * The above definitions do not seem to work if libmono is loaded dynamically as a module.
164  * See bug #78767.
165  */
166 #undef MONO_THREAD_VAR_OFFSET
167 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
168 #endif
169
170 #elif defined(TARGET_MACH) && (defined(__i386__) || defined(__x86_64__))
171
172 #define MONO_HAVE_FAST_TLS
173 #define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
174 #define MONO_FAST_TLS_GET(x) pthread_getspecific(x)
175 #define MONO_FAST_TLS_ADDR(x) (mono_mach_get_tls_address_from_thread (pthread_self (), x))
176 #define MONO_FAST_TLS_INIT(x) pthread_key_create(&x, NULL)
177 #define MONO_FAST_TLS_DECLARE(x) static pthread_key_t x;
178
179 #define MONO_THREAD_VAR_OFFSET(x,y) ({  \
180         __typeof__(x) _x = (x);                 \
181         pthread_key_t _y;       \
182         (void) (&_x == &_y);            \
183         y = (gint32) x; })
184 #else /* no HAVE_KW_THREAD */
185
186 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
187
188 /*Macros to facilitate user code*/
189 #define MONO_FAST_TLS_INIT(x)
190 #endif
191
192 #if defined(MONO_HAVE_FAST_TLS) && !defined(MONO_FAST_TLS_ADDR)
193 #define MONO_FAST_TLS_ADDR(x) (&(x))
194 #endif
195
196
197 /* Deal with Microsoft C compiler differences */
198 #ifdef _MSC_VER
199
200 #include <math.h>
201
202 #if _MSC_VER < 1800 /* VS 2013 */
203 #define strtoull _strtoui64
204 #endif
205
206 #include <float.h>
207 #define trunc(x)        (((x) < 0) ? ceil((x)) : floor((x)))
208 #if _MSC_VER < 1800 /* VS 2013 */
209 #define isnan(x)        _isnan(x)
210 #define isinf(x)        (_isnan(x) ? 0 : (_fpclass(x) == _FPCLASS_NINF) ? -1 : (_fpclass(x) == _FPCLASS_PINF) ? 1 : 0)
211 #define isnormal(x)     _finite(x)
212 #endif
213
214 #define popen           _popen
215 #define pclose          _pclose
216
217 #include <direct.h>
218 #define mkdir(x)        _mkdir(x)
219
220 /* GCC specific functions aren't available */
221 #define __builtin_return_address(x)     NULL
222
223 #define __func__ __FUNCTION__
224
225 #include <BaseTsd.h>
226 typedef SSIZE_T ssize_t;
227
228 /*
229  * SSIZE_MAX is not defined in MSVC, so define it here.
230  *
231  * These values come from MinGW64, and are public domain.
232  *
233  */
234 #ifndef SSIZE_MAX
235 #ifdef _WIN64
236 #define SSIZE_MAX _I64_MAX
237 #else
238 #define SSIZE_MAX INT_MAX
239 #endif
240 #endif
241
242 #endif /* _MSC_VER */
243
244 #if !defined(_MSC_VER) && !defined(PLATFORM_SOLARIS) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MONOTOUCH) && HAVE_VISIBILITY_HIDDEN
245 #define MONO_INTERNAL __attribute__ ((visibility ("hidden")))
246 #if MONO_LLVM_LOADED
247 #define MONO_LLVM_INTERNAL 
248 #else
249 #define MONO_LLVM_INTERNAL MONO_INTERNAL
250 #endif
251 #else
252 #define MONO_INTERNAL 
253 #define MONO_LLVM_INTERNAL 
254 #endif
255
256 #if HAVE_DEPRECATED
257 #define MONO_DEPRECATED __attribute__ ((deprecated))
258 #else
259 #define MONO_DEPRECATED 
260 #endif
261
262 #ifdef __GNUC__
263 #define MONO_ALWAYS_INLINE __attribute__((always_inline))
264 #elif defined(_MSC_VER)
265 #define MONO_ALWAYS_INLINE __forceinline
266 #else
267 #define MONO_ALWAYS_INLINE
268 #endif
269
270 #ifdef __GNUC__
271 #define MONO_NEVER_INLINE __attribute__((noinline))
272 #elif defined(_MSC_VER)
273 #define MONO_NEVER_INLINE __declspec(noinline)
274 #else
275 #define MONO_NEVER_INLINE
276 #endif
277
278 #endif /* __UTILS_MONO_COMPILER_H__*/
279