+#define MONO_MAX_UNWIND_CODES 22
+
+typedef enum _UNWIND_OP_CODES {
+ UWOP_PUSH_NONVOL = 0, /* info == register number */
+ UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */
+ UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */
+ UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
+ UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */
+ UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
+ UWOP_SAVE_XMM128, /* info == XMM reg number, offset in next slot */
+ UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
+ UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
+} UNWIND_CODE_OPS;
+
+typedef union _UNWIND_CODE {
+ struct {
+ guchar CodeOffset;
+ guchar UnwindOp : 4;
+ guchar OpInfo : 4;
+ };
+ gushort FrameOffset;
+} UNWIND_CODE, *PUNWIND_CODE;
+
+typedef struct _UNWIND_INFO {
+ guchar Version : 3;
+ guchar Flags : 5;
+ guchar SizeOfProlog;
+ guchar CountOfCodes;
+ guchar FrameRegister : 4;
+ guchar FrameOffset : 4;
+ UNWIND_CODE UnwindCode[MONO_MAX_UNWIND_CODES];
+/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
+ * union {
+ * OPTIONAL ULONG ExceptionHandler;
+ * OPTIONAL ULONG FunctionEntry;
+ * };
+ * OPTIONAL ULONG ExceptionData[]; */
+} UNWIND_INFO, *PUNWIND_INFO;
+
+static inline guint
+mono_arch_unwindinfo_get_size (guchar code_count)
+{
+ // Returned size will be used as the allocated size for unwind data trailing the memory used by compiled method.
+ // Windows x64 ABI have some requirements on the data written into this memory. Both the RUNTIME_FUNCTION
+ // and UNWIND_INFO struct needs to be DWORD aligned and the number of elements in unwind codes array
+ // should have an even number of entries, while the count stored in UNWIND_INFO struct should hold the real number
+ // of unwind codes. Adding extra bytes to the total size will make sure we can properly align the RUNTIME_FUNCTION
+ // struct. Since our UNWIND_INFO follows RUNTIME_FUNCTION struct in memory, it will automatically be DWORD aligned
+ // as well. Also make sure to allocate room for a padding UNWIND_CODE, if needed.
+ return (sizeof (mgreg_t) + sizeof (UNWIND_INFO)) -
+ (sizeof (UNWIND_CODE) * ((MONO_MAX_UNWIND_CODES - ((code_count + 1) & ~1))));
+}
+
+guchar
+mono_arch_unwindinfo_get_code_count (GSList *unwind_ops);
+
+guint
+mono_arch_unwindinfo_init_method_unwind_info (gpointer cfg);
+
+void
+mono_arch_unwindinfo_install_method_unwind_info (gpointer *monoui, gpointer code, guint code_size);
+
+void
+mono_arch_unwindinfo_install_tramp_unwind_info (GSList *unwind_ops, gpointer code, guint code_size);
+
+void
+mono_arch_code_chunk_new (void *chunk, int size);
+
+void
+mono_arch_code_chunk_destroy (void *chunk);
+
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+#endif /* defined(TARGET_WIN32) && !defined(DISABLE_JIT) */
+
+#ifdef MONO_ARCH_HAVE_UNWIND_TABLE
+// Allocate additional size for max 3 unwind ops (push + fp or sp small|large) + unwind info struct trailing code buffer.
+#define MONO_TRAMPOLINE_UNWINDINFO_SIZE(max_code_count) (mono_arch_unwindinfo_get_size (max_code_count))
+#define MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE (MONO_TRAMPOLINE_UNWINDINFO_SIZE(3))
+
+static inline gboolean
+mono_arch_unwindinfo_validate_size (GSList *unwind_ops, guint max_size)
+{
+ guint current_size = mono_arch_unwindinfo_get_size (mono_arch_unwindinfo_get_code_count (unwind_ops));
+ return current_size <= max_size;
+}
+
+#else
+
+#define MONO_TRAMPOLINE_UNWINDINFO_SIZE(max_code_count) 0
+#define MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE 0
+
+static inline gboolean
+mono_arch_unwindinfo_validate_size (GSList *unwind_ops, guint max_size)
+{
+ return TRUE;
+}