summaryrefslogtreecommitdiff
path: root/mono/utils/mono-compiler.h
blob: 56f5ea90addbdf83bfe8f6a4440d71a568b23b8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#ifndef __UTILS_MONO_COMPILER_H__
#define __UTILS_MONO_COMPILER_H__

/*
 * This file includes macros used in the runtime to encapsulate different
 * compiler behaviours.
 */
#include <config.h>

#ifdef HAVE_KW_THREAD

#define MONO_HAVE_FAST_TLS
#define MONO_FAST_TLS_SET(x,y) x = y
#define MONO_FAST_TLS_GET(x) x
#define MONO_FAST_TLS_INIT(x)
#define MONO_FAST_TLS_DECLARE(x) static __thread gpointer x MONO_TLS_FAST;

#if HAVE_TLS_MODEL_ATTR

#if defined(__PIC__) && !defined(PIC)
/*
 * Must be compiling -fPIE, for executables.  Build PIC
 * but with initial-exec.
 * http://bugs.gentoo.org/show_bug.cgi?id=165547
 */
#define PIC
#define PIC_INITIAL_EXEC
#endif

/* 
 * Define this if you want a faster libmono, which cannot be loaded dynamically as a 
 * module.
 */
//#define PIC_INITIAL_EXEC

#if defined(PIC)

#ifdef PIC_INITIAL_EXEC
#define MONO_TLS_FAST __attribute__((tls_model("initial-exec")))
#else
#if defined (__powerpc__)
/* local dynamic requires a call to __tls_get_addr to look up the
   TLS block address via the Dynamic Thread Vector. In this case Thread
   Pointer relative offsets can't be used as this modules TLS was
   allocated separately (none contiguoiusly) from the initial TLS
   block.

   For now we will disable this. */
#define MONO_TLS_FAST
#else
#define MONO_TLS_FAST __attribute__((tls_model("local-dynamic")))
#endif
#endif

#else

#define MONO_TLS_FAST __attribute__((tls_model("local-exec")))

#endif

#else
#define MONO_TLS_FAST 
#endif

#if defined(__GNUC__) && defined(__i386__)
#if defined(PIC)
#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)
#else
#define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("movl $" #var "@ntpoff, %0" : "=r" (offset))
#endif
#elif defined(__x86_64__)
#if defined(PIC)
// This only works if libmono is linked into the application
#define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;  __asm ("movq " #var "@GOTTPOFF(%%rip), %0" : "=r" (foo)); offset = foo; } while (0)
#else
#define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;  __asm ("movq $" #var "@TPOFF, %0" : "=r" (foo)); offset = foo; } while (0)
#endif
#elif defined(__ia64__) && !defined(__INTEL_COMPILER)
#if defined(PIC)
#define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @ltoff(@tprel(" #var "#)), gp ;; ld8 %0 = [%0]\n" : "=r" (offset))
#else
#define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @tprel(" #var "#), r0 ;;\n" : "=r" (offset))
#endif
#elif defined(__arm__) && defined(__ARM_EABI__) && !defined(PIC)
#define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("	ldr	%0, 1f; b 2f; 1: .word " #var "(tpoff); 2:" : "=r" (offset))
#elif defined(__mono_ppc__) && defined(__GNUC__)
#if defined(PIC)
#ifdef PIC_INITIAL_EXEC

#if defined(__mono_ppc64__)
#define MONO_THREAD_VAR_OFFSET(var,offset) \
	do { long off; \
	__asm (	"ld	%0," #var "@got@tprel(2)\n" \
	: "=r" (off)); \
	(offset) = off; } while (0)
#else
/* must be powerpc32 */
#define MONO_THREAD_VAR_OFFSET(var,offset) \
	__asm (	"lwz	%0," #var "@got@tprel(30)\n" \
	: "=r" (offset))
#endif

#else

/* local dynamic requires a call to __tls_get_addr to look up the
   TLS block address via the Dynamic Thread Vector. In this case Thread
   Pointer relative offsets can't be used as this modules TLS was
   allocated separately (none contiguoiusly) from the initial TLS
   block.

   For now we will disable this. */
#define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1

#endif
#else
/* Must be local-exec TLS */
#define MONO_THREAD_VAR_OFFSET(var,offset) \
	__asm (	"lis	%0," #var "@tprel@ha\n" \
		"addi	%0,%0, " #var "@tprel@l\n" \
	: "=r" (offset))
#endif
#elif defined(__s390x__)
# if defined(PIC)
// This only works if libmono is linked into the application
#  define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;  				\
						__asm__ ("basr	%%r1,0\n\t"			\
							 "j	0f\n\t"				\
							 ".quad " #var "@TLSGD\n\t"		\
							 "0:\n\t"				\
							 "lg	%%r2,4(%%r1)\n\t"		\
							 "brasl	%%r14,__tls_get_offset@PLT:tls_gdcall:"#var"\n\t" \
							 "lgr	%0,%%r2\n\t"			\
							: "=r" (foo) : 				\
							: "1", "2", "14", "cc");		\
						offset = foo; } while (0)
# else
#  define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;  				\
						__asm__ ("basr	%%r1,0\n\t"			\
							 "j	0f\n\t"				\
							 ".quad " #var "@NTPOFF\n"		\
							 "0:\n\t"				\
							 "lg	%0,4(%%r1)\n\t"			\
							: "=r" (foo) : : "1");			\
						offset = foo; } while (0)
# endif

#else
#define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
#endif

#if defined(PIC) && !defined(PIC_INITIAL_EXEC)
/* 
 * The above definitions do not seem to work if libmono is loaded dynamically as a module.
 * See bug #78767.
 */
#undef MONO_THREAD_VAR_OFFSET
#define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
#endif

#elif defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))

#define MONO_HAVE_FAST_TLS
#define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
#define MONO_FAST_TLS_GET(x) pthread_getspecific(x)
#define MONO_FAST_TLS_ADDR(x) (mono_mach_get_tls_address_from_thread (pthread_self (), x))
#define MONO_FAST_TLS_INIT(x) pthread_key_create(&x, NULL)
#define MONO_FAST_TLS_DECLARE(x) static pthread_key_t x;

#define MONO_THREAD_VAR_OFFSET(x,y) ({	\
	typeof(x) _x = (x);			\
	pthread_key_t _y;	\
	(void) (&_x == &_y);		\
	y = (gint32) x; })
#else /* no HAVE_KW_THREAD */

#define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1

/*Macros to facilitate user code*/
#define MONO_FAST_TLS_INIT(x)
#endif

#if defined(MONO_HAVE_FAST_TLS) && !defined(MONO_FAST_TLS_ADDR)
#define MONO_FAST_TLS_ADDR(x) (&(x))
#endif


/* Deal with Microsoft C compiler differences */
#ifdef _MSC_VER

#include <float.h>
#define isnan(x)	_isnan(x)
#define trunc(x)	(((x) < 0) ? ceil((x)) : floor((x)))
#define isinf(x)	(_isnan(x) ? 0 : (_fpclass(x) == _FPCLASS_NINF) ? -1 : (_fpclass(x) == _FPCLASS_PINF) ? 1 : 0)
#define isnormal(x)	_finite(x)

#define popen		_popen
#define pclose		_pclose

#include <direct.h>
#define mkdir(x)	_mkdir(x)

/* GCC specific functions aren't available */
#define __builtin_return_address(x)	NULL

#define __func__ __FUNCTION__

#endif /* _MSC_VER */

#if !defined(_MSC_VER) && !defined(PLATFORM_SOLARIS) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MONOTOUCH) && HAVE_VISIBILITY_HIDDEN
#define MONO_INTERNAL __attribute__ ((visibility ("hidden")))
#if MONO_LLVM_LOADED
#define MONO_LLVM_INTERNAL 
#else
#define MONO_LLVM_INTERNAL MONO_INTERNAL
#endif
#else
#define MONO_INTERNAL 
#define MONO_LLVM_INTERNAL 
#endif

#if HAVE_DEPRECATED
#define MONO_DEPRECATED __attribute__ ((deprecated))
#else
#define MONO_DEPRECATED 
#endif

#ifdef __GNUC__
#define MONO_ALWAYS_INLINE __attribute__((always_inline))
#elif defined(_MSC_VER)
#define MONO_ALWAYS_INLINE __forceinline
#else
#define MONO_ALWAYS_INLINE
#endif

#endif /* __UTILS_MONO_COMPILER_H__*/