1 #ifndef __UTILS_MONO_COMPILER_H__
2 #define __UTILS_MONO_COMPILER_H__
5 * This file includes macros used in the runtime to encapsulate different
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;
18 #if HAVE_TLS_MODEL_ATTR
20 #if defined(__PIC__) && !defined(PIC)
22 * Must be compiling -fPIE, for executables. Build PIC
23 * but with initial-exec.
24 * http://bugs.gentoo.org/show_bug.cgi?id=165547
27 #define PIC_INITIAL_EXEC
31 * Define this if you want a faster libmono, which cannot be loaded dynamically as a
34 //#define PIC_INITIAL_EXEC
38 #ifdef PIC_INITIAL_EXEC
39 #define MONO_TLS_FAST __attribute__((tls_model("initial-exec")))
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
48 For now we will disable this. */
51 #define MONO_TLS_FAST __attribute__((tls_model("local-dynamic")))
57 #define MONO_TLS_FAST __attribute__((tls_model("local-exec")))
65 #if defined(__GNUC__) && defined(__i386__)
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)
69 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("movl $" #var "@ntpoff, %0" : "=r" (offset))
71 #elif defined(__x86_64__)
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)
76 #define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; __asm ("movq $" #var "@TPOFF, %0" : "=r" (foo)); offset = foo; } while (0)
78 #elif defined(__ia64__) && !defined(__INTEL_COMPILER)
80 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @ltoff(@tprel(" #var "#)), gp ;; ld8 %0 = [%0]\n" : "=r" (offset))
82 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @tprel(" #var "#), r0 ;;\n" : "=r" (offset))
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" \
90 #elif defined(__mono_ppc__) && defined(__GNUC__)
92 #ifdef PIC_INITIAL_EXEC
94 #if defined(__mono_ppc64__)
95 #define MONO_THREAD_VAR_OFFSET(var,offset) \
97 __asm ( "ld %0," #var "@got@tprel(2)\n" \
99 (offset) = off; } while (0)
101 /* must be powerpc32 */
102 #define MONO_THREAD_VAR_OFFSET(var,offset) \
103 __asm ( "lwz %0," #var "@got@tprel(30)\n" \
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
115 For now we will disable this. */
116 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
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" \
126 #elif defined(__s390x__)
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" \
132 ".quad " #var "@TLSGD\n\t" \
134 "lg %%r2,4(%%r1)\n\t" \
135 "brasl %%r14,__tls_get_offset@PLT:tls_gdcall:"#var"\n\t" \
138 : "1", "2", "14", "cc"); \
139 offset = foo; } while (0)
141 # define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; \
142 __asm__ ("basr %%r1,0\n\t" \
144 ".quad " #var "@NTPOFF\n" \
146 "lg %0,4(%%r1)\n\t" \
147 : "=r" (foo) : : "1"); \
148 offset = foo; } while (0)
152 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
155 #if defined(PIC) && !defined(PIC_INITIAL_EXEC)
157 * The above definitions do not seem to work if libmono is loaded dynamically as a module.
160 #undef MONO_THREAD_VAR_OFFSET
161 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
164 #elif defined(TARGET_MACH) && (defined(__i386__) || defined(__x86_64__))
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;
173 #define MONO_THREAD_VAR_OFFSET(x,y) ({ \
174 typeof(x) _x = (x); \
176 (void) (&_x == &_y); \
178 #else /* no HAVE_KW_THREAD */
180 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
182 /*Macros to facilitate user code*/
183 #define MONO_FAST_TLS_INIT(x)
186 #if defined(MONO_HAVE_FAST_TLS) && !defined(MONO_FAST_TLS_ADDR)
187 #define MONO_FAST_TLS_ADDR(x) (&(x))
191 /* Deal with Microsoft C compiler differences */
196 #if _MSC_VER < 1800 /* VS 2013 */
197 #define strtoull _strtoui64
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)
209 #define pclose _pclose
212 #define mkdir(x) _mkdir(x)
214 /* GCC specific functions aren't available */
215 #define __builtin_return_address(x) NULL
217 #define __func__ __FUNCTION__
220 typedef SSIZE_T ssize_t;
223 * SSIZE_MAX is not defined in MSVC, so define it here.
225 * These values come from MinGW64, and are public domain.
230 #define SSIZE_MAX _I64_MAX
232 #define SSIZE_MAX INT_MAX
236 #endif /* _MSC_VER */
238 #if !defined(_MSC_VER) && !defined(PLATFORM_SOLARIS) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MONOTOUCH) && HAVE_VISIBILITY_HIDDEN
239 #define MONO_INTERNAL __attribute__ ((visibility ("hidden")))
241 #define MONO_LLVM_INTERNAL
243 #define MONO_LLVM_INTERNAL MONO_INTERNAL
246 #define MONO_INTERNAL
247 #define MONO_LLVM_INTERNAL
251 #define MONO_DEPRECATED __attribute__ ((deprecated))
253 #define MONO_DEPRECATED
257 #define MONO_ALWAYS_INLINE __attribute__((always_inline))
258 #elif defined(_MSC_VER)
259 #define MONO_ALWAYS_INLINE __forceinline
261 #define MONO_ALWAYS_INLINE
265 #define MONO_NEVER_INLINE __attribute__((noinline))
266 #elif defined(_MSC_VER)
267 #define MONO_NEVER_INLINE __declspec(noinline)
269 #define MONO_NEVER_INLINE
272 #endif /* __UTILS_MONO_COMPILER_H__*/