6cb60f2c387585a4c4f58a91df0dc044a5215631
[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(__aarch64__) && !defined(PIC)
87 #define MONO_THREAD_VAR_OFFSET(var,offset) \
88         __asm ( "mov %0, #0\n add %0, %0, #:tprel_hi12:" #var "\n add %0, %0, #:tprel_lo12_nc:" #var "\n" \
89                         : "=r" (offset))
90 #elif defined(__mono_ppc__) && defined(__GNUC__)
91 #if defined(PIC)
92 #ifdef PIC_INITIAL_EXEC
93
94 #if defined(__mono_ppc64__)
95 #define MONO_THREAD_VAR_OFFSET(var,offset) \
96         do { long off; \
97         __asm ( "ld     %0," #var "@got@tprel(2)\n" \
98         : "=r" (off)); \
99         (offset) = off; } while (0)
100 #else
101 /* must be powerpc32 */
102 #define MONO_THREAD_VAR_OFFSET(var,offset) \
103         __asm ( "lwz    %0," #var "@got@tprel(30)\n" \
104         : "=r" (offset))
105 #endif
106
107 #else
108
109 /* local dynamic requires a call to __tls_get_addr to look up the
110    TLS block address via the Dynamic Thread Vector. In this case Thread
111    Pointer relative offsets can't be used as this modules TLS was
112    allocated separately (none contiguoiusly) from the initial TLS
113    block.
114
115    For now we will disable this. */
116 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
117
118 #endif
119 #else
120 /* Must be local-exec TLS */
121 #define MONO_THREAD_VAR_OFFSET(var,offset) \
122         __asm ( "lis    %0," #var "@tprel@ha\n" \
123                 "addi   %0,%0, " #var "@tprel@l\n" \
124         : "=r" (offset))
125 #endif
126 #elif defined(__s390x__)
127 # if defined(PIC)
128 // This only works if libmono is linked into the application
129 #  define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                  \
130                                                 __asm__ ("basr  %%r1,0\n\t"                     \
131                                                          "j     0f\n\t"                         \
132                                                          ".quad " #var "@TLSGD\n\t"             \
133                                                          "0:\n\t"                               \
134                                                          "lg    %%r2,4(%%r1)\n\t"               \
135                                                          "brasl %%r14,__tls_get_offset@PLT:tls_gdcall:"#var"\n\t" \
136                                                          "lgr   %0,%%r2\n\t"                    \
137                                                         : "=r" (foo) :                          \
138                                                         : "1", "2", "14", "cc");                \
139                                                 offset = foo; } while (0)
140 # else
141 #  define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;                                  \
142                                                 __asm__ ("basr  %%r1,0\n\t"                     \
143                                                          "j     0f\n\t"                         \
144                                                          ".quad " #var "@NTPOFF\n"              \
145                                                          "0:\n\t"                               \
146                                                          "lg    %0,4(%%r1)\n\t"                 \
147                                                         : "=r" (foo) : : "1");                  \
148                                                 offset = foo; } while (0)
149 # endif
150
151 #else
152 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
153 #endif
154
155 #if defined(PIC) && !defined(PIC_INITIAL_EXEC)
156 /* 
157  * The above definitions do not seem to work if libmono is loaded dynamically as a module.
158  * See bug #78767.
159  */
160 #undef MONO_THREAD_VAR_OFFSET
161 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
162 #endif
163
164 #elif defined(TARGET_MACH) && (defined(__i386__) || defined(__x86_64__))
165
166 #define MONO_HAVE_FAST_TLS
167 #define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
168 #define MONO_FAST_TLS_GET(x) pthread_getspecific(x)
169 #define MONO_FAST_TLS_ADDR(x) (mono_mach_get_tls_address_from_thread (pthread_self (), x))
170 #define MONO_FAST_TLS_INIT(x) pthread_key_create(&x, NULL)
171 #define MONO_FAST_TLS_DECLARE(x) static pthread_key_t x;
172
173 #define MONO_THREAD_VAR_OFFSET(x,y) ({  \
174         __typeof__(x) _x = (x);                 \
175         pthread_key_t _y;       \
176         (void) (&_x == &_y);            \
177         y = (gint32) x; })
178 #else /* no HAVE_KW_THREAD */
179
180 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
181
182 /*Macros to facilitate user code*/
183 #define MONO_FAST_TLS_INIT(x)
184 #endif
185
186 #if defined(MONO_HAVE_FAST_TLS) && !defined(MONO_FAST_TLS_ADDR)
187 #define MONO_FAST_TLS_ADDR(x) (&(x))
188 #endif
189
190
191 /* Deal with Microsoft C compiler differences */
192 #ifdef _MSC_VER
193
194 #include <math.h>
195
196 #if _MSC_VER < 1800 /* VS 2013 */
197 #define strtoull _strtoui64
198 #endif
199
200 #include <float.h>
201 #define trunc(x)        (((x) < 0) ? ceil((x)) : floor((x)))
202 #if _MSC_VER < 1800 /* VS 2013 */
203 #define isnan(x)        _isnan(x)
204 #define isinf(x)        (_isnan(x) ? 0 : (_fpclass(x) == _FPCLASS_NINF) ? -1 : (_fpclass(x) == _FPCLASS_PINF) ? 1 : 0)
205 #define isnormal(x)     _finite(x)
206 #endif
207
208 #define popen           _popen
209 #define pclose          _pclose
210
211 #include <direct.h>
212 #define mkdir(x)        _mkdir(x)
213
214 /* GCC specific functions aren't available */
215 #define __builtin_return_address(x)     NULL
216
217 #define __func__ __FUNCTION__
218
219 #include <BaseTsd.h>
220 typedef SSIZE_T ssize_t;
221
222 /*
223  * SSIZE_MAX is not defined in MSVC, so define it here.
224  *
225  * These values come from MinGW64, and are public domain.
226  *
227  */
228 #ifndef SSIZE_MAX
229 #ifdef _WIN64
230 #define SSIZE_MAX _I64_MAX
231 #else
232 #define SSIZE_MAX INT_MAX
233 #endif
234 #endif
235
236 #endif /* _MSC_VER */
237
238 #if !defined(_MSC_VER) && !defined(PLATFORM_SOLARIS) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MONOTOUCH) && HAVE_VISIBILITY_HIDDEN
239 #define MONO_INTERNAL __attribute__ ((visibility ("hidden")))
240 #if MONO_LLVM_LOADED
241 #define MONO_LLVM_INTERNAL 
242 #else
243 #define MONO_LLVM_INTERNAL MONO_INTERNAL
244 #endif
245 #else
246 #define MONO_INTERNAL 
247 #define MONO_LLVM_INTERNAL 
248 #endif
249
250 #if HAVE_DEPRECATED
251 #define MONO_DEPRECATED __attribute__ ((deprecated))
252 #else
253 #define MONO_DEPRECATED 
254 #endif
255
256 #ifdef __GNUC__
257 #define MONO_ALWAYS_INLINE __attribute__((always_inline))
258 #elif defined(_MSC_VER)
259 #define MONO_ALWAYS_INLINE __forceinline
260 #else
261 #define MONO_ALWAYS_INLINE
262 #endif
263
264 #ifdef __GNUC__
265 #define MONO_NEVER_INLINE __attribute__((noinline))
266 #elif defined(_MSC_VER)
267 #define MONO_NEVER_INLINE __declspec(noinline)
268 #else
269 #define MONO_NEVER_INLINE
270 #endif
271
272 #endif /* __UTILS_MONO_COMPILER_H__*/
273