1 #ifndef __UTILS_MONO_COMPILER_H__
2 #define __UTILS_MONO_COMPILER_H__
5 * This file includes macros used in the runtime to encapsulate different
11 #define MONO_ATTR_USED __attribute__ ((used))
13 #define MONO_ATTR_USED
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
33 #define PIC_INITIAL_EXEC
37 * Define this if you want a faster libmono, which cannot be loaded dynamically as a
40 //#define PIC_INITIAL_EXEC
44 #ifdef PIC_INITIAL_EXEC
45 #define MONO_TLS_FAST __attribute__((tls_model("initial-exec")))
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
54 For now we will disable this. */
57 #define MONO_TLS_FAST __attribute__((tls_model("local-dynamic")))
63 #define MONO_TLS_FAST __attribute__((tls_model("local-exec")))
71 #if defined(__GNUC__) && defined(__i386__)
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)
75 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("movl $" #var "@ntpoff, %0" : "=r" (offset))
77 #elif defined(__x86_64__)
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)
82 #define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; __asm ("movq $" #var "@TPOFF, %0" : "=r" (foo)); offset = foo; } while (0)
84 #elif defined(__ia64__) && !defined(__INTEL_COMPILER)
86 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @ltoff(@tprel(" #var "#)), gp ;; ld8 %0 = [%0]\n" : "=r" (offset))
88 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @tprel(" #var "#), r0 ;;\n" : "=r" (offset))
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" \
96 #elif defined(__mono_ppc__) && defined(__GNUC__)
98 #ifdef PIC_INITIAL_EXEC
100 #if defined(__mono_ppc64__)
101 #define MONO_THREAD_VAR_OFFSET(var,offset) \
103 __asm ( "ld %0," #var "@got@tprel(2)\n" \
105 (offset) = off; } while (0)
107 /* must be powerpc32 */
108 #define MONO_THREAD_VAR_OFFSET(var,offset) \
109 __asm ( "lwz %0," #var "@got@tprel(30)\n" \
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
121 For now we will disable this. */
122 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
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" \
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" \
139 ".quad " #var "@TLSGD\n" \
141 "lg %%r2,4(%%r1)\n\t" \
142 "brasl %%r14,__tls_get_offset@PLT:tls_gdcall:"#var"\n\t" \
145 : "1", "2", "14", "cc"); \
146 offset = foo; } while (0)
148 # define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; \
149 __asm__ ("lg %0," #var "@GOTNTPOFF(%%r12)\n\t" \
151 offset = foo; } while (0)
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" \
158 offset = foo; } while (0)
161 # define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; \
162 __asm__ ("basr %%r1,0\n\t" \
164 ".quad " #var "@NTPOFF\n" \
166 "lg %0,4(%%r1)\n\t" \
167 : "=r" (foo) : : "1"); \
168 offset = foo; } while (0)
171 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
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.
179 #undef MONO_THREAD_VAR_OFFSET
180 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
183 #elif !defined(MONO_CROSS_COMPILE) && defined(PLATFORM_MACOSX) && (defined(__i386__) || defined(__x86_64__))
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;
192 #define MONO_THREAD_VAR_OFFSET(x,y) ({ \
193 __typeof__(x) _x = (x); \
195 (void) (&_x == &_y); \
198 #elif !defined(MONO_CROSS_COMPILE) && (defined(PLATFORM_ANDROID) || defined(TARGET_IOS)) && defined(TARGET_ARM)
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;
206 #define MONO_THREAD_VAR_OFFSET(var, offset) do { offset = (int)var; } while (0)
208 #else /* no HAVE_KW_THREAD */
210 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
212 /*Macros to facilitate user code*/
213 #define MONO_FAST_TLS_INIT(x)
216 #if defined(MONO_HAVE_FAST_TLS) && !defined(MONO_FAST_TLS_ADDR)
217 #define MONO_FAST_TLS_ADDR(x) (&(x))
221 /* Deal with Microsoft C compiler differences */
226 #if _MSC_VER < 1800 /* VS 2013 */
227 #define strtoull _strtoui64
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)
239 #define pclose _pclose
242 #define mkdir(x) _mkdir(x)
244 /* GCC specific functions aren't available */
245 #define __builtin_return_address(x) NULL
247 #define __func__ __FUNCTION__
250 typedef SSIZE_T ssize_t;
253 * SSIZE_MAX is not defined in MSVC, so define it here.
255 * These values come from MinGW64, and are public domain.
260 #define SSIZE_MAX _I64_MAX
262 #define SSIZE_MAX INT_MAX
266 #endif /* _MSC_VER */
268 #if !defined(_MSC_VER) && !defined(PLATFORM_SOLARIS) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MONOTOUCH) && HAVE_VISIBILITY_HIDDEN
270 #define MONO_LLVM_INTERNAL MONO_API
272 #define MONO_LLVM_INTERNAL
275 #define MONO_LLVM_INTERNAL
279 #define MONO_DEPRECATED __attribute__ ((deprecated))
281 #define MONO_DEPRECATED
285 #define MONO_ALWAYS_INLINE __attribute__((always_inline))
286 #elif defined(_MSC_VER)
287 #define MONO_ALWAYS_INLINE __forceinline
289 #define MONO_ALWAYS_INLINE
293 #define MONO_NEVER_INLINE __attribute__((noinline))
294 #elif defined(_MSC_VER)
295 #define MONO_NEVER_INLINE __declspec(noinline)
297 #define MONO_NEVER_INLINE
301 #define MONO_COLD __attribute__((cold))
306 #endif /* __UTILS_MONO_COMPILER_H__*/