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