Build mono runtime under none desktop Windows API family, adjustments and cleanup.
[mono.git] / mono / mini / mini-amd64.h
1 #ifndef __MONO_MINI_AMD64_H__
2 #define __MONO_MINI_AMD64_H__
3
4 #include <mono/arch/amd64/amd64-codegen.h>
5 #include <mono/utils/mono-sigcontext.h>
6 #include <mono/utils/mono-context.h>
7 #include <glib.h>
8
9 #ifdef HOST_WIN32
10 #include <windows.h>
11 /* use SIG* defines if possible */
12 #ifdef HAVE_SIGNAL_H
13 #include <signal.h>
14 #endif
15
16 #if !defined(_MSC_VER)
17 /* sigcontext surrogate */
18 struct sigcontext {
19         guint64 eax;
20         guint64 ebx;
21         guint64 ecx;
22         guint64 edx;
23         guint64 ebp;
24         guint64 esp;
25     guint64 esi;
26         guint64 edi;
27         guint64 eip;
28 };
29 #endif
30
31 typedef void (* MonoW32ExceptionHandler) (int _dummy, EXCEPTION_POINTERS *info, void *context);
32 void win32_seh_init(void);
33 void win32_seh_cleanup(void);
34 void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler);
35
36 #ifndef SIGFPE
37 #define SIGFPE 4
38 #endif
39
40 #ifndef SIGILL
41 #define SIGILL 8
42 #endif
43
44 #ifndef SIGSEGV
45 #define SIGSEGV 11
46 #endif
47
48 LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep);
49
50 #endif /* HOST_WIN32 */
51
52 #ifdef sun    // Solaris x86
53 #  undef SIGSEGV_ON_ALTSTACK
54 #  define MONO_ARCH_NOMAP32BIT
55
56 struct sigcontext {
57         unsigned short gs, __gsh;
58         unsigned short fs, __fsh;
59         unsigned short es, __esh;
60         unsigned short ds, __dsh;
61         unsigned long edi;
62         unsigned long esi;
63         unsigned long ebp;
64         unsigned long esp;
65         unsigned long ebx;
66         unsigned long edx;
67         unsigned long ecx;
68         unsigned long eax;
69         unsigned long trapno;
70         unsigned long err;
71         unsigned long eip;
72         unsigned short cs, __csh;
73         unsigned long eflags;
74         unsigned long esp_at_signal;
75         unsigned short ss, __ssh;
76         unsigned long fpstate[95];
77       unsigned long filler[5];
78 };
79 #endif  // sun, Solaris x86
80
81 #ifndef DISABLE_SIMD
82 #define MONO_ARCH_SIMD_INTRINSICS 1
83 #define MONO_ARCH_NEED_SIMD_BANK 1
84 #define MONO_ARCH_USE_SHARED_FP_SIMD_BANK 1
85 #endif
86
87
88
89 #if defined(__APPLE__)
90 #define MONO_ARCH_SIGNAL_STACK_SIZE MINSIGSTKSZ
91 #else
92 #define MONO_ARCH_SIGNAL_STACK_SIZE (16 * 1024)
93 #endif
94
95 #define MONO_ARCH_HAVE_RESTORE_STACK_SUPPORT 1
96
97 #define MONO_ARCH_CPU_SPEC mono_amd64_desc
98
99 #define MONO_MAX_IREGS 16
100
101 #define MONO_MAX_FREGS AMD64_XMM_NREG
102
103 #define MONO_ARCH_FP_RETURN_REG AMD64_XMM0
104
105 #ifdef TARGET_WIN32
106 /* xmm5 is used as a scratch register */
107 #define MONO_ARCH_CALLEE_FREGS 0x1f
108 /* xmm6:xmm15 */
109 #define MONO_ARCH_CALLEE_SAVED_FREGS (0xffff - 0x3f)
110 #define MONO_ARCH_FP_SCRATCH_REG AMD64_XMM5
111 #else
112 /* xmm15 is used as a scratch register */
113 #define MONO_ARCH_CALLEE_FREGS 0x7fff
114 #define MONO_ARCH_CALLEE_SAVED_FREGS 0
115 #define MONO_ARCH_FP_SCRATCH_REG AMD64_XMM15
116 #endif
117
118 #define MONO_MAX_XREGS MONO_MAX_FREGS
119
120 #define MONO_ARCH_CALLEE_XREGS MONO_ARCH_CALLEE_FREGS
121 #define MONO_ARCH_CALLEE_SAVED_XREGS MONO_ARCH_CALLEE_SAVED_FREGS
122
123
124 #define MONO_ARCH_CALLEE_REGS AMD64_CALLEE_REGS
125 #define MONO_ARCH_CALLEE_SAVED_REGS AMD64_CALLEE_SAVED_REGS
126
127 #define MONO_ARCH_USE_FPSTACK FALSE
128 #define MONO_ARCH_FPSTACK_SIZE 0
129
130 #define MONO_ARCH_INST_FIXED_REG(desc) ((desc == '\0') ? -1 : ((desc == 'i' ? -1 : ((desc == 'a') ? AMD64_RAX : ((desc == 's') ? AMD64_RCX : ((desc == 'd') ? AMD64_RDX : ((desc == 'A') ? MONO_AMD64_ARG_REG1 : -1)))))))
131
132 /* RDX is clobbered by the opcode implementation before accessing sreg2 */
133 #define MONO_ARCH_INST_SREG2_MASK(ins) (((ins [MONO_INST_CLOB] == 'a') || (ins [MONO_INST_CLOB] == 'd')) ? (1 << AMD64_RDX) : 0)
134
135 #define MONO_ARCH_INST_IS_REGPAIR(desc) FALSE
136 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (-1)
137
138 #define MONO_ARCH_FRAME_ALIGNMENT 16
139
140 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get 
141  * reproduceable results for benchmarks */
142 #define MONO_ARCH_CODE_ALIGNMENT 32
143
144 /*This is the max size of the locals area of a given frame. I think 1MB is a safe default for now*/
145 #define MONO_ARCH_MAX_FRAME_SIZE 0x100000
146
147 struct MonoLMF {
148         /* 
149          * If the lowest bit is set, then this LMF has the rip field set. Otherwise,
150          * the rip field is not set, and the rsp field points to the stack location where
151          * the caller ip is saved.
152          * If the second lowest bit is set, then this is a MonoLMFExt structure, and
153          * the other fields are not valid.
154          * If the third lowest bit is set, then this is a MonoLMFTramp structure, and
155          * the 'rbp' field is not valid.
156          */
157         gpointer    previous_lmf;
158         guint64     rip;
159         guint64     rbp;
160         guint64     rsp;
161 };
162
163 /* LMF structure used by the JIT trampolines */
164 typedef struct {
165         struct MonoLMF lmf;
166         MonoContext *ctx;
167         gpointer lmf_addr;
168 } MonoLMFTramp;
169
170 typedef struct MonoCompileArch {
171         gint32 localloc_offset;
172         gint32 reg_save_area_offset;
173         gint32 stack_alloc_size;
174         gint32 sp_fp_offset;
175         guint32 saved_iregs;
176         gboolean omit_fp, omit_fp_computed;
177         gpointer cinfo;
178         gint32 async_point_count;
179         gpointer vret_addr_loc;
180 #ifdef HOST_WIN32
181         gpointer        unwindinfo;
182 #endif
183         gpointer seq_point_info_var;
184         gpointer ss_trigger_page_var;
185         gpointer ss_tramp_var;
186         gpointer bp_tramp_var;
187         gpointer lmf_var;
188 } MonoCompileArch;
189
190 #ifdef TARGET_WIN32
191
192 static AMD64_Reg_No param_regs [] = { AMD64_RCX, AMD64_RDX, AMD64_R8, AMD64_R9 };
193
194 static AMD64_XMM_Reg_No float_param_regs [] = { AMD64_XMM0, AMD64_XMM1, AMD64_XMM2, AMD64_XMM3 };
195
196 static AMD64_Reg_No return_regs [] = { AMD64_RAX };
197
198 static AMD64_XMM_Reg_No float_return_regs [] = { AMD64_XMM0 };
199
200 #define PARAM_REGS G_N_ELEMENTS(param_regs)
201 #define FLOAT_PARAM_REGS G_N_ELEMENTS(float_param_regs)
202 #define RETURN_REGS G_N_ELEMENTS(return_regs)
203 #define FLOAT_RETURN_REGS G_N_ELEMENTS(float_return_regs)
204
205 #else
206 #define PARAM_REGS 6
207 #define FLOAT_PARAM_REGS 8
208
209 static AMD64_Reg_No param_regs [] = { AMD64_RDI, AMD64_RSI, AMD64_RDX, AMD64_RCX, AMD64_R8, AMD64_R9 };
210
211 static AMD64_Reg_No return_regs [] = { AMD64_RAX, AMD64_RDX };
212 #endif
213
214 typedef struct {
215         /* Method address to call */
216         gpointer addr;
217         /* The trampoline reads this, so keep the size explicit */
218         int ret_marshal;
219         /* If ret_marshal != NONE, this is the reg of the vret arg, else -1 (used in out case) */
220         /* Equivalent of vret_arg_slot in the x86 implementation. */
221         int vret_arg_reg;
222         /* The stack slot where the return value will be stored (used in in case) */
223         int vret_slot;
224         int stack_usage, map_count;
225         /* If not -1, then make a virtual call using this vtable offset */
226         int vcall_offset;
227         /* If 1, make an indirect call to the address in the rgctx reg */
228         int calli;
229         /* Whenever this is a in or an out call */
230         int gsharedvt_in;
231         /* Maps stack slots/registers in the caller to the stack slots/registers in the callee */
232         int map [MONO_ZERO_LEN_ARRAY];
233 } GSharedVtCallInfo;
234
235 /* Structure used by the sequence points in AOTed code */
236 typedef struct {
237         gpointer ss_tramp_addr;
238         gpointer bp_addrs [MONO_ZERO_LEN_ARRAY];
239 } SeqPointInfo;
240
241 #define DYN_CALL_STACK_ARGS 6
242
243 typedef struct {
244         mgreg_t regs [PARAM_REGS + DYN_CALL_STACK_ARGS];
245         mgreg_t res;
246         guint8 *ret;
247         double fregs [8];
248         mgreg_t has_fp;
249         guint8 buffer [256];
250 } DynCallArgs;
251
252 typedef enum {
253         ArgInIReg,
254         ArgInFloatSSEReg,
255         ArgInDoubleSSEReg,
256         ArgOnStack,
257         ArgValuetypeInReg,
258         ArgValuetypeAddrInIReg,
259         ArgValuetypeAddrOnStack,
260         /* gsharedvt argument passed by addr */
261         ArgGSharedVtInReg,
262         ArgGSharedVtOnStack,
263         /* Variable sized gsharedvt argument passed/returned by addr */
264         ArgGsharedvtVariableInReg,
265         ArgNone /* only in pair_storage */
266 } ArgStorage;
267
268 typedef struct {
269         gint16 offset;
270         gint8  reg;
271         ArgStorage storage : 8;
272
273         /* Only if storage == ArgValuetypeInReg */
274         ArgStorage pair_storage [2];
275         gint8 pair_regs [2];
276         /* The size of each pair (bytes) */
277         int pair_size [2];
278         int nregs;
279         /* Only if storage == ArgOnStack */
280         int arg_size; // Bytes, will always be rounded up/aligned to 8 byte boundary
281         guint8 pass_empty_struct : 1; // Set in scenarios when empty structs needs to be represented as argument.
282 } ArgInfo;
283
284 typedef struct {
285         int nargs;
286         guint32 stack_usage;
287         guint32 reg_usage;
288         guint32 freg_usage;
289         gboolean need_stack_align;
290         gboolean gsharedvt;
291         /* The index of the vret arg in the argument list */
292         int vret_arg_index;
293         ArgInfo ret;
294         ArgInfo sig_cookie;
295         ArgInfo args [1];
296 } CallInfo;
297
298
299 #define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) do { (ctx)->gregs [AMD64_RAX] = (gsize)exc; } while (0)
300 #define MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG(ctx, sel) do { (ctx)->gregs [AMD64_RDX] = (gsize)(sel); } while (0)
301
302 #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
303
304 #ifdef _MSC_VER
305
306 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx, start_func) do { \
307     guint64 stackptr; \
308         mono_arch_flush_register_windows (); \
309         stackptr = ((guint64)_AddressOfReturnAddress () - sizeof (void*));\
310         MONO_CONTEXT_SET_IP ((ctx), (start_func)); \
311         MONO_CONTEXT_SET_BP ((ctx), stackptr); \
312         MONO_CONTEXT_SET_SP ((ctx), stackptr); \
313 } while (0)
314
315 #else
316
317 /* 
318  * __builtin_frame_address () is broken on some older gcc versions in the presence of
319  * frame pointer elimination, see bug #82095.
320  */
321 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,start_func) do {        \
322         int tmp; \
323         guint64 stackptr = (guint64)&tmp; \
324                 mono_arch_flush_register_windows ();    \
325                 MONO_CONTEXT_SET_IP ((ctx), (start_func));      \
326                 MONO_CONTEXT_SET_BP ((ctx), stackptr);  \
327                 MONO_CONTEXT_SET_SP ((ctx), stackptr);  \
328         } while (0)
329
330 #endif
331
332 /*
333  * some icalls like mono_array_new_va needs to be called using a different 
334  * calling convention.
335  */
336 #define MONO_ARCH_VARARG_ICALLS 1
337
338 #if !defined( HOST_WIN32 ) && defined (HAVE_SIGACTION)
339
340 #define MONO_ARCH_USE_SIGACTION 1
341
342 #ifdef HAVE_WORKING_SIGALTSTACK
343
344 #define MONO_ARCH_SIGSEGV_ON_ALTSTACK
345
346 #endif
347
348 #endif /* !HOST_WIN32 */
349
350 #if !defined(__linux__)
351 #define MONO_ARCH_NOMAP32BIT 1
352 #endif
353
354 #ifdef TARGET_WIN32
355 #define MONO_AMD64_ARG_REG1 AMD64_RCX
356 #define MONO_AMD64_ARG_REG2 AMD64_RDX
357 #define MONO_AMD64_ARG_REG3 AMD64_R8
358 #define MONO_AMD64_ARG_REG4 AMD64_R9
359 #else
360 #define MONO_AMD64_ARG_REG1 AMD64_RDI
361 #define MONO_AMD64_ARG_REG2 AMD64_RSI
362 #define MONO_AMD64_ARG_REG3 AMD64_RDX
363 #define MONO_AMD64_ARG_REG4 AMD64_RCX
364 #endif
365
366 #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
367 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
368
369 #define MONO_ARCH_EMULATE_CONV_R8_UN    1
370 #define MONO_ARCH_EMULATE_FREM 1
371 #define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1
372
373 #define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
374 #define MONO_ARCH_HAVE_INVALIDATE_METHOD 1
375 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
376 #define MONO_ARCH_HAVE_TLS_GET (mono_amd64_have_tls_get ())
377 #define MONO_ARCH_IMT_REG AMD64_R10
378 #define MONO_ARCH_IMT_SCRATCH_REG AMD64_R11
379 #define MONO_ARCH_VTABLE_REG MONO_AMD64_ARG_REG1
380 /*
381  * We use r10 for the imt/rgctx register rather than r11 because r11 is
382  * used by the trampoline as a scratch register and hence might be
383  * clobbered across method call boundaries.
384  */
385 #define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG
386 #define MONO_ARCH_EXC_REG AMD64_RAX
387 #define MONO_ARCH_HAVE_CMOV_OPS 1
388 #define MONO_ARCH_HAVE_EXCEPTIONS_INIT 1
389 #define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
390 #define MONO_ARCH_HAVE_LIVERANGE_OPS 1
391 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
392 #define MONO_ARCH_HAVE_GET_TRAMPOLINES 1
393
394 #define MONO_ARCH_AOT_SUPPORTED 1
395 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
396
397 #define MONO_ARCH_SUPPORT_TASKLETS 1
398
399 #define MONO_ARCH_GSHARED_SUPPORTED 1
400 #define MONO_ARCH_DYN_CALL_SUPPORTED 1
401 #define MONO_ARCH_DYN_CALL_PARAM_AREA (DYN_CALL_STACK_ARGS * 8)
402
403 #define MONO_ARCH_LLVM_SUPPORTED 1
404 #define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1
405 #define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD_AOT 1
406 #define MONO_ARCH_HAVE_CARD_TABLE_WBARRIER 1
407 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
408 #define MONO_ARCH_GC_MAPS_SUPPORTED 1
409 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1
410 #define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1
411 #define MONO_ARCH_HAVE_CREATE_LLVM_NATIVE_THUNK 1
412 #define MONO_ARCH_HAVE_OP_TAIL_CALL 1
413 #define MONO_ARCH_HAVE_TRANSLATE_TLS_OFFSET 1
414 #define MONO_ARCH_HAVE_DUMMY_INIT 1
415 #define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1
416 #define MONO_ARCH_HAVE_PATCH_CODE_NEW 1
417 #define MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT 1
418 #define MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE 1
419
420 #if defined(TARGET_OSX) || defined(__linux__)
421 #define MONO_ARCH_HAVE_UNWIND_BACKTRACE 1
422 #endif
423
424 #if defined(TARGET_OSX) || defined(__linux__) || defined(TARGET_WIN32)
425 #define MONO_ARCH_HAVE_TLS_GET_REG 1
426 #endif
427
428 #define MONO_ARCH_GSHAREDVT_SUPPORTED 1
429
430
431 #if defined(TARGET_APPLETVOS)
432 /* No signals */
433 #define MONO_ARCH_NEED_DIV_CHECK 1
434 #endif
435
436 /* Used for optimization, not complete */
437 #define MONO_ARCH_IS_OP_MEMBASE(opcode) ((opcode) == OP_X86_PUSH_MEMBASE)
438
439 #define MONO_ARCH_EMIT_BOUNDS_CHECK(cfg, array_reg, offset, index_reg) do { \
440             MonoInst *inst; \
441             MONO_INST_NEW ((cfg), inst, OP_AMD64_ICOMPARE_MEMBASE_REG); \
442             inst->inst_basereg = array_reg; \
443             inst->inst_offset = offset; \
444             inst->sreg2 = index_reg; \
445             MONO_ADD_INS ((cfg)->cbb, inst); \
446             MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException"); \
447        } while (0)
448
449 void 
450 mono_amd64_patch (unsigned char* code, gpointer target);
451
452 void
453 mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
454                                                         guint64 dummy5, guint64 dummy6,
455                                                         MonoContext *mctx, MonoObject *exc, gboolean rethrow);
456
457 void
458 mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
459                                                                    guint64 dummy5, guint64 dummy6,
460                                                                    MonoContext *mctx, guint32 ex_token_index, gint64 pc_offset);
461
462 void
463 mono_amd64_resume_unwind (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
464                                                   guint64 dummy5, guint64 dummy6,
465                                                   MonoContext *mctx, guint32 dummy7, gint64 dummy8);
466
467 gpointer
468 mono_amd64_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg);
469
470 guint64
471 mono_amd64_get_original_ip (void);
472
473 guint8*
474 mono_amd64_emit_tls_get (guint8* code, int dreg, int tls_offset);
475
476 gboolean
477 mono_amd64_have_tls_get (void);
478
479 GSList*
480 mono_amd64_get_exception_trampolines (gboolean aot);
481
482 int
483 mono_amd64_get_tls_gs_offset (void) MONO_LLVM_INTERNAL;
484
485 gpointer
486 mono_amd64_handler_block_trampoline_helper (void);
487
488 #ifdef TARGET_WIN32
489
490 void mono_arch_unwindinfo_add_push_nonvol (gpointer* monoui, gpointer codebegin, gpointer nextip, guchar reg );
491 void mono_arch_unwindinfo_add_set_fpreg (gpointer* monoui, gpointer codebegin, gpointer nextip, guchar reg );
492 void mono_arch_unwindinfo_add_alloc_stack (gpointer* monoui, gpointer codebegin, gpointer nextip, guint size );
493 guint mono_arch_unwindinfo_get_size (gpointer monoui);
494 void mono_arch_unwindinfo_install_unwind_info (gpointer* monoui, gpointer code, guint code_size);
495
496 #define MONO_ARCH_HAVE_UNWIND_TABLE 1
497 #endif
498
499 CallInfo* mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig);
500
501 #endif /* __MONO_MINI_AMD64_H__ */  
502