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 * When embedding, you have to define MONO_ZERO_LEN_ARRAY before including any
12 * other Mono header file if you use a different compiler from the one used to
15 #ifndef MONO_ZERO_LEN_ARRAY
17 #define MONO_ZERO_LEN_ARRAY 0
19 #define MONO_ZERO_LEN_ARRAY 1
24 #define MONO_ATTR_USED __attribute__ ((used))
26 #define MONO_ATTR_USED
31 #define MONO_HAVE_FAST_TLS
32 #define MONO_FAST_TLS_SET(x,y) x = y
33 #define MONO_FAST_TLS_GET(x) x
34 #define MONO_FAST_TLS_INIT(x)
35 #define MONO_FAST_TLS_DECLARE(x) static __thread gpointer x MONO_TLS_FAST MONO_ATTR_USED;
37 #if HAVE_TLS_MODEL_ATTR
39 #if defined(__PIC__) && !defined(PIC)
41 * Must be compiling -fPIE, for executables. Build PIC
42 * but with initial-exec.
43 * http://bugs.gentoo.org/show_bug.cgi?id=165547
46 #define PIC_INITIAL_EXEC
50 * Define this if you want a faster libmono, which cannot be loaded dynamically as a
53 //#define PIC_INITIAL_EXEC
57 #ifdef PIC_INITIAL_EXEC
58 #define MONO_TLS_FAST __attribute__((tls_model("initial-exec")))
60 #if defined (__powerpc__)
61 /* local dynamic requires a call to __tls_get_addr to look up the
62 TLS block address via the Dynamic Thread Vector. In this case Thread
63 Pointer relative offsets can't be used as this modules TLS was
64 allocated separately (none contiguoiusly) from the initial TLS
67 For now we will disable this. */
70 #define MONO_TLS_FAST __attribute__((tls_model("local-dynamic")))
76 #define MONO_TLS_FAST __attribute__((tls_model("local-exec")))
84 #if defined(__GNUC__) && defined(__i386__)
86 #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)
88 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("movl $" #var "@ntpoff, %0" : "=r" (offset))
90 #elif defined(__x86_64__)
92 // This only works if libmono is linked into the application
93 #define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; __asm ("movq " #var "@GOTTPOFF(%%rip), %0" : "=r" (foo)); offset = foo; } while (0)
95 #define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; __asm ("movq $" #var "@TPOFF, %0" : "=r" (foo)); offset = foo; } while (0)
97 #elif defined(__ia64__) && !defined(__INTEL_COMPILER)
99 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @ltoff(@tprel(" #var "#)), gp ;; ld8 %0 = [%0]\n" : "=r" (offset))
101 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @tprel(" #var "#), r0 ;;\n" : "=r" (offset))
103 #elif defined(__arm__) && defined(__ARM_EABI__) && !defined(PIC)
104 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm (" ldr %0, 1f; b 2f; 1: .word " #var "(tpoff); 2:" : "=r" (offset))
105 #elif defined(__aarch64__) && !defined(PIC)
106 #define MONO_THREAD_VAR_OFFSET(var,offset) \
107 __asm ( "mov %0, #0\n add %0, %0, #:tprel_hi12:" #var "\n add %0, %0, #:tprel_lo12_nc:" #var "\n" \
109 #elif defined(__mono_ppc__) && defined(__GNUC__)
111 #ifdef PIC_INITIAL_EXEC
113 #if defined(__mono_ppc64__)
114 #define MONO_THREAD_VAR_OFFSET(var,offset) \
116 __asm ( "ld %0," #var "@got@tprel(2)\n" \
118 (offset) = off; } while (0)
120 /* must be powerpc32 */
121 #define MONO_THREAD_VAR_OFFSET(var,offset) \
122 __asm ( "lwz %0," #var "@got@tprel(30)\n" \
128 /* local dynamic requires a call to __tls_get_addr to look up the
129 TLS block address via the Dynamic Thread Vector. In this case Thread
130 Pointer relative offsets can't be used as this modules TLS was
131 allocated separately (none contiguoiusly) from the initial TLS
134 For now we will disable this. */
135 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
139 /* Must be local-exec TLS */
140 #define MONO_THREAD_VAR_OFFSET(var,offset) \
141 __asm ( "lis %0," #var "@tprel@ha\n" \
142 "addi %0,%0, " #var "@tprel@l\n" \
145 #elif defined(__s390x__)
146 # if defined(__PIC__)
147 # if !defined(__PIE__)
148 // This only works if libmono is linked into the application
149 # define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; \
150 __asm__ ("basr %%r1,0\n\t" \
152 ".quad " #var "@TLSGD\n" \
154 "lg %%r2,4(%%r1)\n\t" \
155 "brasl %%r14,__tls_get_offset@PLT:tls_gdcall:"#var"\n\t" \
158 : "1", "2", "14", "cc"); \
159 offset = foo; } while (0)
161 # define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; \
162 __asm__ ("lg %0," #var "@GOTNTPOFF(%%r12)\n\t" \
164 offset = foo; } while (0)
166 # define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; \
167 __asm__ ("larl %%r1," #var "@INDNTPOFF\n\t" \
168 "lg %0,0(%%r1)\n\t" \
171 offset = foo; } while (0)
174 # define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; \
175 __asm__ ("basr %%r1,0\n\t" \
177 ".quad " #var "@NTPOFF\n" \
179 "lg %0,4(%%r1)\n\t" \
180 : "=r" (foo) : : "1"); \
181 offset = foo; } while (0)
184 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
187 #if defined(PIC) && !defined(PIC_INITIAL_EXEC)
189 * The above definitions do not seem to work if libmono is loaded dynamically as a module.
192 #undef MONO_THREAD_VAR_OFFSET
193 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
196 #elif !defined(MONO_CROSS_COMPILE) && defined(PLATFORM_MACOSX) && (defined(__i386__) || defined(__x86_64__))
198 #define MONO_HAVE_FAST_TLS 1
199 #define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
200 #define MONO_FAST_TLS_GET(x) pthread_getspecific(x)
201 #define MONO_FAST_TLS_ADDR(x) (mono_mach_get_tls_address_from_thread (pthread_self (), x))
202 #define MONO_FAST_TLS_INIT(x) pthread_key_create(&x, NULL)
203 #define MONO_FAST_TLS_DECLARE(x) static pthread_key_t x;
205 #define MONO_THREAD_VAR_OFFSET(x,y) ({ \
206 __typeof__(x) _x = (x); \
208 (void) (&_x == &_y); \
211 #elif !defined(MONO_CROSS_COMPILE) && (defined(PLATFORM_ANDROID) || defined(TARGET_IOS)) && defined(TARGET_ARM)
213 #define MONO_HAVE_FAST_TLS
214 #define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
215 #define MONO_FAST_TLS_GET(x) pthread_getspecific(x)
216 #define MONO_FAST_TLS_INIT(x) pthread_key_create(&x, NULL)
217 #define MONO_FAST_TLS_DECLARE(x) static pthread_key_t x;
219 #define MONO_THREAD_VAR_OFFSET(var, offset) do { offset = (int)var; } while (0)
221 #else /* no HAVE_KW_THREAD */
223 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
225 /*Macros to facilitate user code*/
226 #define MONO_FAST_TLS_INIT(x)
229 #if defined(MONO_HAVE_FAST_TLS) && !defined(MONO_FAST_TLS_ADDR)
230 #define MONO_FAST_TLS_ADDR(x) (&(x))
234 /* Deal with Microsoft C compiler differences */
239 #if _MSC_VER < 1800 /* VS 2013 */
240 #define strtoull _strtoui64
244 #define trunc(x) (((x) < 0) ? ceil((x)) : floor((x)))
245 #if _MSC_VER < 1800 /* VS 2013 */
246 #define isnan(x) _isnan(x)
247 #define isinf(x) (_isnan(x) ? 0 : (_fpclass(x) == _FPCLASS_NINF) ? -1 : (_fpclass(x) == _FPCLASS_PINF) ? 1 : 0)
248 #define isnormal(x) _finite(x)
252 #define pclose _pclose
255 #define mkdir(x) _mkdir(x)
257 /* GCC specific functions aren't available */
258 #define __builtin_return_address(x) NULL
260 #define __func__ __FUNCTION__
263 typedef SSIZE_T ssize_t;
266 * SSIZE_MAX is not defined in MSVC, so define it here.
268 * These values come from MinGW64, and are public domain.
273 #define SSIZE_MAX _I64_MAX
275 #define SSIZE_MAX INT_MAX
279 #endif /* _MSC_VER */
281 #if !defined(_MSC_VER) && !defined(PLATFORM_SOLARIS) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MONOTOUCH) && HAVE_VISIBILITY_HIDDEN
283 #define MONO_LLVM_INTERNAL MONO_API
285 #define MONO_LLVM_INTERNAL
288 #define MONO_LLVM_INTERNAL
292 #define MONO_DEPRECATED __attribute__ ((deprecated))
294 #define MONO_DEPRECATED
298 #define MONO_ALWAYS_INLINE __attribute__((always_inline))
299 #elif defined(_MSC_VER)
300 #define MONO_ALWAYS_INLINE __forceinline
302 #define MONO_ALWAYS_INLINE
306 #define MONO_NEVER_INLINE __attribute__((noinline))
307 #elif defined(_MSC_VER)
308 #define MONO_NEVER_INLINE __declspec(noinline)
310 #define MONO_NEVER_INLINE
314 #define MONO_COLD __attribute__((cold))
319 #endif /* __UTILS_MONO_COMPILER_H__*/