"Fossies" - the Fresh Open Source Software Archive

Member "mono-6.12.0.122/mono/mini/mini-amd64.h" (22 Feb 2021, 19639 Bytes) of package /linux/misc/mono-sources/mono/mono-6.12.0.122.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "mini-amd64.h": 5.20.1.34_vs_6.8.0.96.

    1 /**
    2  * \file
    3  */
    4 
    5 #ifndef __MONO_MINI_AMD64_H__
    6 #define __MONO_MINI_AMD64_H__
    7 
    8 #include <mono/arch/amd64/amd64-codegen.h>
    9 #include <mono/utils/mono-sigcontext.h>
   10 #include <mono/utils/mono-context.h>
   11 #include <glib.h>
   12 
   13 #ifdef HOST_WIN32
   14 #include <windows.h>
   15 #include <signal.h>
   16 
   17 #if !defined(_MSC_VER)
   18 /* sigcontext surrogate */
   19 struct sigcontext {
   20     guint64 eax;
   21     guint64 ebx;
   22     guint64 ecx;
   23     guint64 edx;
   24     guint64 ebp;
   25     guint64 esp;
   26     guint64 esi;
   27     guint64 edi;
   28     guint64 eip;
   29 };
   30 #endif
   31 
   32 typedef void MONO_SIG_HANDLER_SIGNATURE ((*MonoW32ExceptionHandler));
   33 void win32_seh_init(void);
   34 void win32_seh_cleanup(void);
   35 void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler);
   36 
   37 #ifndef SIGFPE
   38 #define SIGFPE 4
   39 #endif
   40 
   41 #ifndef SIGILL
   42 #define SIGILL 8
   43 #endif
   44 
   45 #ifndef SIGSEGV
   46 #define SIGSEGV 11
   47 #endif
   48 
   49 LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep);
   50 
   51 typedef struct {
   52     SRWLOCK lock;
   53     PVOID handle;
   54     gsize begin_range;
   55     gsize end_range;
   56     PRUNTIME_FUNCTION rt_funcs;
   57     DWORD rt_funcs_current_count;
   58     DWORD rt_funcs_max_count;
   59 } DynamicFunctionTableEntry;
   60 
   61 #define MONO_UNWIND_INFO_RT_FUNC_SIZE 128
   62 
   63 typedef BOOLEAN (WINAPI* RtlInstallFunctionTableCallbackPtr)(
   64     DWORD64 TableIdentifier,
   65     DWORD64 BaseAddress,
   66     DWORD Length,
   67     PGET_RUNTIME_FUNCTION_CALLBACK Callback,
   68     PVOID Context,
   69     PCWSTR OutOfProcessCallbackDll);
   70 
   71 typedef BOOLEAN (WINAPI* RtlDeleteFunctionTablePtr)(
   72     PRUNTIME_FUNCTION FunctionTable);
   73 
   74 // On Win8/Win2012Server and later we can use dynamic growable function tables
   75 // instead of RtlInstallFunctionTableCallback. This gives us the benefit to
   76 // include all needed unwind upon registration.
   77 typedef DWORD (NTAPI* RtlAddGrowableFunctionTablePtr)(
   78     PVOID * DynamicTable,
   79     PRUNTIME_FUNCTION FunctionTable,
   80     DWORD EntryCount,
   81     DWORD MaximumEntryCount,
   82     ULONG_PTR RangeBase,
   83     ULONG_PTR RangeEnd);
   84 
   85 typedef VOID (NTAPI* RtlGrowFunctionTablePtr)(
   86     PVOID DynamicTable,
   87     DWORD NewEntryCount);
   88 
   89 typedef VOID (NTAPI* RtlDeleteGrowableFunctionTablePtr)(
   90     PVOID DynamicTable);
   91 
   92 #endif /* HOST_WIN32 */
   93 
   94 #ifdef sun    // Solaris x86
   95 #  undef SIGSEGV_ON_ALTSTACK
   96 #  define MONO_ARCH_NOMAP32BIT
   97 
   98 struct sigcontext {
   99         unsigned short gs, __gsh;
  100         unsigned short fs, __fsh;
  101         unsigned short es, __esh;
  102         unsigned short ds, __dsh;
  103         unsigned long edi;
  104         unsigned long esi;
  105         unsigned long ebp;
  106         unsigned long esp;
  107         unsigned long ebx;
  108         unsigned long edx;
  109         unsigned long ecx;
  110         unsigned long eax;
  111         unsigned long trapno;
  112         unsigned long err;
  113         unsigned long eip;
  114         unsigned short cs, __csh;
  115         unsigned long eflags;
  116         unsigned long esp_at_signal;
  117         unsigned short ss, __ssh;
  118         unsigned long fpstate[95];
  119       unsigned long filler[5];
  120 };
  121 #endif  // sun, Solaris x86
  122 
  123 #ifndef DISABLE_SIMD
  124 #define MONO_ARCH_SIMD_INTRINSICS 1
  125 #define MONO_ARCH_NEED_SIMD_BANK 1
  126 #define MONO_ARCH_USE_SHARED_FP_SIMD_BANK 1
  127 #endif
  128 
  129 
  130 
  131 #if defined(__APPLE__)
  132 #define MONO_ARCH_SIGNAL_STACK_SIZE MINSIGSTKSZ
  133 #else
  134 #define MONO_ARCH_SIGNAL_STACK_SIZE (16 * 1024)
  135 #endif
  136 
  137 #define MONO_ARCH_CPU_SPEC mono_amd64_desc
  138 
  139 #define MONO_MAX_IREGS 16
  140 
  141 #define MONO_MAX_FREGS AMD64_XMM_NREG
  142 
  143 #define MONO_ARCH_FP_RETURN_REG AMD64_XMM0
  144 
  145 #ifdef TARGET_WIN32
  146 /* xmm5 is used as a scratch register */
  147 #define MONO_ARCH_CALLEE_FREGS 0x1f
  148 /* xmm6:xmm15 */
  149 #define MONO_ARCH_CALLEE_SAVED_FREGS (0xffff - 0x3f)
  150 #define MONO_ARCH_FP_SCRATCH_REG AMD64_XMM5
  151 #else
  152 /* xmm15 is used as a scratch register */
  153 #define MONO_ARCH_CALLEE_FREGS 0x7fff
  154 #define MONO_ARCH_CALLEE_SAVED_FREGS 0
  155 #define MONO_ARCH_FP_SCRATCH_REG AMD64_XMM15
  156 #endif
  157 
  158 #define MONO_MAX_XREGS MONO_MAX_FREGS
  159 
  160 #define MONO_ARCH_CALLEE_XREGS MONO_ARCH_CALLEE_FREGS
  161 #define MONO_ARCH_CALLEE_SAVED_XREGS MONO_ARCH_CALLEE_SAVED_FREGS
  162 
  163 
  164 #define MONO_ARCH_CALLEE_REGS AMD64_CALLEE_REGS
  165 #define MONO_ARCH_CALLEE_SAVED_REGS AMD64_CALLEE_SAVED_REGS
  166 
  167 #define MONO_ARCH_USE_FPSTACK FALSE
  168 
  169 #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)))))))
  170 
  171 /* RDX is clobbered by the opcode implementation before accessing sreg2 */
  172 #define MONO_ARCH_INST_SREG2_MASK(ins) (((ins [MONO_INST_CLOB] == 'a') || (ins [MONO_INST_CLOB] == 'd')) ? (1 << AMD64_RDX) : 0)
  173 
  174 #define MONO_ARCH_INST_IS_REGPAIR(desc) FALSE
  175 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (-1)
  176 
  177 #define MONO_ARCH_FRAME_ALIGNMENT 16
  178 
  179 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get 
  180  * reproduceable results for benchmarks */
  181 #define MONO_ARCH_CODE_ALIGNMENT 32
  182 
  183 struct MonoLMF {
  184     /* 
  185      * The rsp field points to the stack location where the caller ip is saved.
  186      * If the second lowest bit is set, then this is a MonoLMFExt structure, and
  187      * the other fields are not valid.
  188      * If the third lowest bit is set, then this is a MonoLMFTramp structure, and
  189      * the 'rbp' field is not valid.
  190      */
  191     gpointer    previous_lmf;
  192     guint64     rbp;
  193     guint64     rsp;
  194 };
  195 
  196 /* LMF structure used by the JIT trampolines */
  197 typedef struct {
  198     struct MonoLMF lmf;
  199     MonoContext *ctx;
  200     gpointer lmf_addr;
  201 } MonoLMFTramp;
  202 
  203 typedef struct MonoCompileArch {
  204     gint32 localloc_offset;
  205     gint32 reg_save_area_offset;
  206     gint32 stack_alloc_size;
  207     gint32 sp_fp_offset;
  208     guint32 saved_iregs;
  209     gboolean omit_fp;
  210     gboolean omit_fp_computed;
  211     CallInfo *cinfo;
  212     gint32 async_point_count;
  213     MonoInst *vret_addr_loc;
  214     MonoInst *seq_point_info_var;
  215     MonoInst *ss_tramp_var;
  216     MonoInst *bp_tramp_var;
  217     MonoInst *lmf_var;
  218 #ifdef HOST_WIN32
  219     struct _UNWIND_INFO* unwindinfo;
  220 #endif
  221 } MonoCompileArch;
  222 
  223 #ifdef TARGET_WIN32
  224 
  225 static const AMD64_Reg_No param_regs [] = { AMD64_RCX, AMD64_RDX, AMD64_R8, AMD64_R9 };
  226 
  227 static const AMD64_XMM_Reg_No float_param_regs [] = { AMD64_XMM0, AMD64_XMM1, AMD64_XMM2, AMD64_XMM3 };
  228 
  229 static const AMD64_Reg_No return_regs [] = { AMD64_RAX };
  230 
  231 static const AMD64_XMM_Reg_No float_return_regs [] = { AMD64_XMM0 };
  232 
  233 #define PARAM_REGS G_N_ELEMENTS(param_regs)
  234 #define FLOAT_PARAM_REGS G_N_ELEMENTS(float_param_regs)
  235 #define RETURN_REGS G_N_ELEMENTS(return_regs)
  236 #define FLOAT_RETURN_REGS G_N_ELEMENTS(float_return_regs)
  237 
  238 #else
  239 #define PARAM_REGS 6
  240 #define FLOAT_PARAM_REGS 8
  241 #define RETURN_REGS 2
  242 #define FLOAT_RETURN_REGS 2
  243 
  244 static const AMD64_Reg_No param_regs [] = {AMD64_RDI, AMD64_RSI, AMD64_RDX,
  245                        AMD64_RCX, AMD64_R8,  AMD64_R9};
  246 
  247 static const AMD64_XMM_Reg_No float_param_regs[] = {AMD64_XMM0, AMD64_XMM1, AMD64_XMM2,
  248                              AMD64_XMM3, AMD64_XMM4, AMD64_XMM5,
  249                              AMD64_XMM6, AMD64_XMM7};
  250 
  251 static const AMD64_Reg_No return_regs [] = {AMD64_RAX, AMD64_RDX};
  252 #endif
  253 
  254 typedef struct {
  255     /* Method address to call */
  256     gpointer addr;
  257     /* The trampoline reads this, so keep the size explicit */
  258     int ret_marshal;
  259     /* If ret_marshal != NONE, this is the reg of the vret arg, else -1 (used in out case) */
  260     /* Equivalent of vret_arg_slot in the x86 implementation. */
  261     int vret_arg_reg;
  262     /* The stack slot where the return value will be stored (used in in case) */
  263     int vret_slot;
  264     int stack_usage, map_count;
  265     /* If not -1, then make a virtual call using this vtable offset */
  266     int vcall_offset;
  267     /* If 1, make an indirect call to the address in the rgctx reg */
  268     int calli;
  269     /* Whenever this is a in or an out call */
  270     int gsharedvt_in;
  271     /* Maps stack slots/registers in the caller to the stack slots/registers in the callee */
  272     int map [MONO_ZERO_LEN_ARRAY];
  273 } GSharedVtCallInfo;
  274 
  275 /* Structure used by the sequence points in AOTed code */
  276 struct SeqPointInfo {
  277     gpointer ss_tramp_addr;
  278     gpointer bp_addrs [MONO_ZERO_LEN_ARRAY];
  279 };
  280 
  281 typedef struct {
  282     host_mgreg_t res;
  283     guint8 *ret;
  284     double fregs [8];
  285     host_mgreg_t has_fp;
  286     host_mgreg_t nstack_args;
  287     /* This should come last as the structure is dynamically extended */
  288     host_mgreg_t regs [PARAM_REGS];
  289 } DynCallArgs;
  290 
  291 typedef enum {
  292     ArgInIReg,
  293     ArgInFloatSSEReg,
  294     ArgInDoubleSSEReg,
  295     ArgOnStack,
  296     ArgValuetypeInReg,
  297     ArgValuetypeAddrInIReg,
  298     ArgValuetypeAddrOnStack,
  299     /* gsharedvt argument passed by addr */
  300     ArgGSharedVtInReg,
  301     ArgGSharedVtOnStack,
  302     /* Variable sized gsharedvt argument passed/returned by addr */
  303     ArgGsharedvtVariableInReg,
  304     ArgNone /* only in pair_storage */
  305 } ArgStorage;
  306 
  307 typedef struct {
  308     gint16 offset;
  309     gint8  reg;
  310     ArgStorage storage : 8;
  311 
  312     /* Only if storage == ArgValuetypeInReg */
  313     ArgStorage pair_storage [2];
  314     gint8 pair_regs [2];
  315     /* The size of each pair (bytes) */
  316     int pair_size [2];
  317     int nregs;
  318     /* Only if storage == ArgOnStack */
  319     int arg_size; // Bytes, will always be rounded up/aligned to 8 byte boundary
  320     // Size in bytes for small arguments
  321     int byte_arg_size;
  322     guint8 pass_empty_struct : 1; // Set in scenarios when empty structs needs to be represented as argument.
  323     guint8 is_signed : 1;
  324 } ArgInfo;
  325 
  326 struct CallInfo {
  327     int nargs;
  328     guint32 stack_usage;
  329     guint32 reg_usage;
  330     guint32 freg_usage;
  331     gboolean need_stack_align;
  332     gboolean gsharedvt;
  333     /* The index of the vret arg in the argument list */
  334     int vret_arg_index;
  335     ArgInfo ret;
  336     ArgInfo sig_cookie;
  337     ArgInfo args [1];
  338 };
  339 
  340 typedef struct {
  341     /* General registers */
  342     host_mgreg_t gregs [AMD64_NREG];
  343     /* Floating registers */
  344     double fregs [AMD64_XMM_NREG];
  345     /* Stack usage, used for passing params on stack */
  346     guint32 stack_size;
  347     guint8 *stack;
  348 } CallContext;
  349 
  350 #define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) do { (ctx)->gregs [AMD64_RAX] = (gsize)exc; } while (0)
  351 #define MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG(ctx, sel) do { (ctx)->gregs [AMD64_RDX] = (gsize)(sel); } while (0)
  352 
  353 #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
  354 
  355 #ifdef _MSC_VER
  356 
  357 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx, start_func) do { \
  358     guint64 stackptr; \
  359     stackptr = ((guint64)_AddressOfReturnAddress () - sizeof (void*));\
  360     MONO_CONTEXT_SET_IP ((ctx), (start_func)); \
  361     MONO_CONTEXT_SET_BP ((ctx), stackptr); \
  362     MONO_CONTEXT_SET_SP ((ctx), stackptr); \
  363 } while (0)
  364 
  365 #else
  366 
  367 /* 
  368  * __builtin_frame_address () is broken on some older gcc versions in the presence of
  369  * frame pointer elimination, see bug #82095.
  370  */
  371 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,start_func) do {    \
  372         int tmp; \
  373         guint64 stackptr = (guint64)&tmp; \
  374         MONO_CONTEXT_SET_IP ((ctx), (start_func));  \
  375         MONO_CONTEXT_SET_BP ((ctx), stackptr);  \
  376         MONO_CONTEXT_SET_SP ((ctx), stackptr);  \
  377     } while (0)
  378 
  379 #endif
  380 
  381 #if !defined( HOST_WIN32 ) && !defined(__HAIKU__) && defined (HAVE_SIGACTION)
  382 
  383 #define MONO_ARCH_USE_SIGACTION 1
  384 
  385 #ifdef HAVE_WORKING_SIGALTSTACK
  386 
  387 #define MONO_ARCH_SIGSEGV_ON_ALTSTACK
  388 
  389 #endif
  390 
  391 #endif /* !HOST_WIN32 */
  392 
  393 #if !defined(__linux__)
  394 #define MONO_ARCH_NOMAP32BIT 1
  395 #endif
  396 
  397 #ifdef TARGET_WIN32
  398 #define MONO_AMD64_ARG_REG1 AMD64_RCX
  399 #define MONO_AMD64_ARG_REG2 AMD64_RDX
  400 #define MONO_AMD64_ARG_REG3 AMD64_R8
  401 #define MONO_AMD64_ARG_REG4 AMD64_R9
  402 #else
  403 #define MONO_AMD64_ARG_REG1 AMD64_RDI
  404 #define MONO_AMD64_ARG_REG2 AMD64_RSI
  405 #define MONO_AMD64_ARG_REG3 AMD64_RDX
  406 #define MONO_AMD64_ARG_REG4 AMD64_RCX
  407 #endif
  408 
  409 #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
  410 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
  411 
  412 #define MONO_ARCH_EMULATE_CONV_R8_UN 1
  413 #define MONO_ARCH_EMULATE_FCONV_TO_U8 1
  414 // x64 FullAOT+LLVM fails to pass the basic-float tests without this.
  415 #define MONO_ARCH_EMULATE_FCONV_TO_U4 1
  416 #define MONO_ARCH_EMULATE_FREM 1
  417 #define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1
  418 #define MONO_ARCH_HAVE_INVALIDATE_METHOD 1
  419 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
  420 #define MONO_ARCH_IMT_REG AMD64_R10
  421 #define MONO_ARCH_IMT_SCRATCH_REG AMD64_R11
  422 #define MONO_ARCH_VTABLE_REG MONO_AMD64_ARG_REG1
  423 /*
  424  * We use r10 for the imt/rgctx register rather than r11 because r11 is
  425  * used by the trampoline as a scratch register and hence might be
  426  * clobbered across method call boundaries.
  427  */
  428 #define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG
  429 #define MONO_ARCH_HAVE_CMOV_OPS 1
  430 #define MONO_ARCH_HAVE_EXCEPTIONS_INIT 1
  431 #define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
  432 #define MONO_ARCH_HAVE_GET_TRAMPOLINES 1
  433 
  434 #define MONO_ARCH_INTERPRETER_SUPPORTED 1
  435 #define MONO_ARCH_AOT_SUPPORTED 1
  436 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
  437 
  438 #define MONO_ARCH_SUPPORT_TASKLETS 1
  439 
  440 #define MONO_ARCH_GSHARED_SUPPORTED 1
  441 #define MONO_ARCH_DYN_CALL_SUPPORTED 1
  442 #define MONO_ARCH_DYN_CALL_PARAM_AREA 0
  443 
  444 #define MONO_ARCH_LLVM_SUPPORTED 1
  445 #if defined(HOST_WIN32) && defined(TARGET_WIN32) && !defined(_MSC_VER)
  446 // Only supported for Windows cross compiler builds, host == Win32, target != Win32
  447 // and only using MSVC for none cross compiler builds.
  448 #undef MONO_ARCH_LLVM_SUPPORTED
  449 #endif
  450 
  451 #define MONO_ARCH_HAVE_CARD_TABLE_WBARRIER 1
  452 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
  453 #define MONO_ARCH_GC_MAPS_SUPPORTED 1
  454 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1
  455 #define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1
  456 #define MONO_ARCH_HAVE_CREATE_LLVM_NATIVE_THUNK 1
  457 #define MONO_ARCH_HAVE_OP_TAILCALL_MEMBASE 1
  458 #define MONO_ARCH_HAVE_OP_TAILCALL_REG 1
  459 #define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1
  460 #define MONO_ARCH_HAVE_PATCH_CODE_NEW 1
  461 #define MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT 1
  462 #define MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE 1
  463 #define MONO_ARCH_FLOAT32_SUPPORTED 1
  464 #define MONO_ARCH_LLVM_TARGET_LAYOUT "e-i64:64-i128:128-n8:16:32:64-S128"
  465 
  466 #define MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP
  467 #define MONO_ARCH_HAVE_INTERP_ENTRY_TRAMPOLINE 1
  468 #define MONO_ARCH_HAVE_INTERP_NATIVE_TO_MANAGED 1
  469 
  470 #if defined(TARGET_OSX) || defined(__linux__)
  471 #define MONO_ARCH_HAVE_UNWIND_BACKTRACE 1
  472 #endif
  473 
  474 #define MONO_ARCH_GSHAREDVT_SUPPORTED 1
  475 
  476 
  477 #if defined(HOST_TVOS) || defined(HOST_WATCHOS)
  478 /* Neither tvOS nor watchOS give signal handlers access to a ucontext_t, so we
  479  * can't use signals to translate SIGFPE into a .NET-level exception. */
  480 #define MONO_ARCH_NEED_DIV_CHECK 1
  481 #endif
  482 
  483 /* Used for optimization, not complete */
  484 #define MONO_ARCH_IS_OP_MEMBASE(opcode) ((opcode) == OP_X86_PUSH_MEMBASE)
  485 
  486 #define MONO_ARCH_EMIT_BOUNDS_CHECK(cfg, array_reg, offset, index_reg, ex_name) do { \
  487             MonoInst *inst; \
  488             MONO_INST_NEW ((cfg), inst, OP_AMD64_ICOMPARE_MEMBASE_REG); \
  489             inst->inst_basereg = array_reg; \
  490             inst->inst_offset = offset; \
  491             inst->sreg2 = index_reg; \
  492             MONO_ADD_INS ((cfg)->cbb, inst); \
  493             MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, ex_name); \
  494        } while (0)
  495 
  496 // Does the ABI have a volatile non-parameter register, so tailcall
  497 // can pass context to generics or interfaces?
  498 #define MONO_ARCH_HAVE_VOLATILE_NON_PARAM_REGISTER 1
  499 
  500 void 
  501 mono_amd64_patch (unsigned char* code, gpointer target);
  502 
  503 void
  504 mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
  505                             guint64 dummy5, guint64 dummy6,
  506                             MonoContext *mctx, MonoObject *exc, gboolean rethrow, gboolean preserve_ips);
  507 
  508 void
  509 mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
  510                                    guint64 dummy5, guint64 dummy6,
  511                                    MonoContext *mctx, guint32 ex_token_index, gint64 pc_offset);
  512 
  513 void
  514 mono_amd64_resume_unwind (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
  515                           guint64 dummy5, guint64 dummy6,
  516                           MonoContext *mctx, guint32 dummy7, gint64 dummy8);
  517 
  518 gpointer
  519 mono_amd64_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpointer *callee, gpointer mrgctx_reg);
  520 
  521 GSList*
  522 mono_amd64_get_exception_trampolines (gboolean aot);
  523 
  524 MONO_LLVM_INTERNAL int
  525 mono_amd64_get_tls_gs_offset (void);
  526 
  527 #if defined(TARGET_WIN32) && !defined(DISABLE_JIT)
  528 
  529 #define MONO_ARCH_HAVE_UNWIND_TABLE 1
  530 #define MONO_ARCH_HAVE_CODE_CHUNK_TRACKING 1
  531 
  532 #ifdef ENABLE_CHECKED_BUILD
  533 #define ENABLE_CHECKED_BUILD_UNWINDINFO
  534 #endif
  535 
  536 #define MONO_MAX_UNWIND_CODES 22
  537 
  538 typedef enum _UNWIND_OP_CODES {
  539     UWOP_PUSH_NONVOL = 0, /* info == register number */
  540     UWOP_ALLOC_LARGE,     /* no info, alloc size in next 2 slots */
  541     UWOP_ALLOC_SMALL,     /* info == size of allocation / 8 - 1 */
  542     UWOP_SET_FPREG,       /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
  543     UWOP_SAVE_NONVOL,     /* info == register number, offset in next slot */
  544     UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
  545     UWOP_SAVE_XMM128,     /* info == XMM reg number, offset in next slot */
  546     UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
  547     UWOP_PUSH_MACHFRAME   /* info == 0: no error-code, 1: error-code */
  548 } UNWIND_CODE_OPS;
  549 
  550 typedef union _UNWIND_CODE {
  551     struct {
  552         guchar CodeOffset;
  553         guchar UnwindOp : 4;
  554         guchar OpInfo   : 4;
  555     };
  556     gushort FrameOffset;
  557 } UNWIND_CODE, *PUNWIND_CODE;
  558 
  559 typedef struct _UNWIND_INFO {
  560     guchar Version       : 3;
  561     guchar Flags         : 5;
  562     guchar SizeOfProlog;
  563     guchar CountOfCodes;
  564     guchar FrameRegister : 4;
  565     guchar FrameOffset   : 4;
  566     UNWIND_CODE UnwindCode[MONO_MAX_UNWIND_CODES];
  567 /*  UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
  568  *  union {
  569  *      OPTIONAL ULONG ExceptionHandler;
  570  *      OPTIONAL ULONG FunctionEntry;
  571  *  };
  572  *  OPTIONAL ULONG ExceptionData[]; */
  573 } UNWIND_INFO, *PUNWIND_INFO;
  574 
  575 static inline guint
  576 mono_arch_unwindinfo_get_size (guchar code_count)
  577 {
  578     // Returned size will be used as the allocated size for unwind data trailing the memory used by compiled method.
  579     // Windows x64 ABI have some requirements on the data written into this memory. Both the RUNTIME_FUNCTION
  580     // and UNWIND_INFO struct needs to be DWORD aligned and the number of elements in unwind codes array
  581     // should have an even number of entries, while the count stored in UNWIND_INFO struct should hold the real number
  582     // of unwind codes. Adding extra bytes to the total size will make sure we can properly align the RUNTIME_FUNCTION
  583     // struct. Since our UNWIND_INFO follows RUNTIME_FUNCTION struct in memory, it will automatically be DWORD aligned
  584     // as well. Also make sure to allocate room for a padding UNWIND_CODE, if needed.
  585     return (sizeof (target_mgreg_t) + sizeof (UNWIND_INFO)) -
  586         (sizeof (UNWIND_CODE) * ((MONO_MAX_UNWIND_CODES - ((code_count + 1) & ~1))));
  587 /* FIXME Something simpler should work:
  588     return sizeof (UNWIND_INFO) + sizeof (UNWIND_CODE) * (code_count + (code_count & 1));
  589 */
  590 }
  591 
  592 guchar
  593 mono_arch_unwindinfo_get_code_count (GSList *unwind_ops);
  594 
  595 PUNWIND_INFO
  596 mono_arch_unwindinfo_alloc_unwind_info (GSList *unwind_ops);
  597 
  598 void
  599 mono_arch_unwindinfo_free_unwind_info (PUNWIND_INFO unwind_info);
  600 
  601 guint
  602 mono_arch_unwindinfo_init_method_unwind_info (gpointer cfg);
  603 
  604 void
  605 mono_arch_unwindinfo_install_method_unwind_info (PUNWIND_INFO *monoui, gpointer code, guint code_size);
  606 
  607 void
  608 mono_arch_unwindinfo_install_tramp_unwind_info (GSList *unwind_ops, gpointer code, guint code_size);
  609 
  610 void
  611 mono_arch_code_chunk_new (void *chunk, int size);
  612 
  613 void
  614 mono_arch_code_chunk_destroy (void *chunk);
  615 
  616 #endif /* defined(TARGET_WIN32) && !defined(DISABLE_JIT) */
  617 
  618 #ifdef MONO_ARCH_HAVE_UNWIND_TABLE
  619 // Allocate additional size for max 3 unwind ops (push + fp or sp small|large) + unwind info struct trailing code buffer.
  620 #define MONO_TRAMPOLINE_UNWINDINFO_SIZE(max_code_count) (mono_arch_unwindinfo_get_size (max_code_count))
  621 #define MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE (MONO_TRAMPOLINE_UNWINDINFO_SIZE(3))
  622 
  623 static inline gboolean
  624 mono_arch_unwindinfo_validate_size (GSList *unwind_ops, guint max_size)
  625 {
  626     guint current_size = mono_arch_unwindinfo_get_size (mono_arch_unwindinfo_get_code_count (unwind_ops));
  627     return current_size <= max_size;
  628 }
  629 
  630 #else
  631 
  632 #define MONO_TRAMPOLINE_UNWINDINFO_SIZE(max_code_count) 0
  633 #define MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE 0
  634 
  635 static inline gboolean
  636 mono_arch_unwindinfo_validate_size (GSList *unwind_ops, guint max_size)
  637 {
  638     return TRUE;
  639 }
  640 #endif
  641 
  642 CallInfo* mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig);
  643 
  644 #endif /* __MONO_MINI_AMD64_H__ */  
  645