#include "config.h"
#include <glib.h>
+#ifdef HAVE_SIGNAL_H
#include <signal.h>
+#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#endif
/* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION 103
+#define MONO_AOT_FILE_VERSION 107
//TODO: This is x86/amd64 specific.
#define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6))
MONO_AOT_FILE_FLAG_WITH_LLVM = 1,
MONO_AOT_FILE_FLAG_FULL_AOT = 2,
MONO_AOT_FILE_FLAG_DEBUG = 4,
- MONO_AOT_FILE_FLAG_DIRECT_METHOD_ADDRESSES = 8
} MonoAotFileFlags;
/* This structure is stored in the AOT file */
/* Mono's Global Offset Table */
gpointer got;
+ /* Global Offset Table for LLVM code */
+ gpointer llvm_got;
/* Compiled code for methods */
gpointer methods;
+ gpointer jit_code_start;
+ gpointer jit_code_end;
/* Mono EH Frame created by llc when using LLVM */
gpointer mono_eh_frame;
/* Data blob */
gpointer class_info_offsets;
gpointer method_info_offsets;
gpointer ex_info_offsets;
- gpointer code_offsets;
gpointer method_addresses;
gpointer extra_method_info_offsets;
gpointer extra_method_table;
gpointer got_info_offsets;
+ gpointer llvm_got_info_offsets;
gpointer methods_end;
gpointer unwind_info;
gpointer mem_end;
gpointer unbox_trampolines;
/* Points to the end of the previous table */
gpointer unbox_trampolines_end;
+ /* Points to a table of unbox trampoline addresses/offsets */
+ gpointer unbox_trampoline_addresses;
/* The index of the first GOT slot used by the PLT */
guint32 plt_got_offset_base;
*/
typedef MonoStackFrameInfo StackFrameInfo;
-#define MONO_SEQ_POINT_FLAG_NONEMPTY_STACK 1
-
-typedef struct {
- int il_offset, native_offset, flags;
- /* Indexes of successor sequence points */
- int *next;
- /* Number of entries in next */
- int next_len;
-} SeqPoint;
-
-typedef struct {
- int len;
- SeqPoint seq_points [MONO_ZERO_LEN_ARRAY];
-} MonoSeqPointInfo;
-
#if 0
#define mono_bitset_foreach_bit(set,b,n) \
for (b = 0; b < n; b++)\
#define MONO_IS_SETCC(ins) ((((ins)->opcode >= OP_CEQ) && ((ins)->opcode <= OP_CLT_UN)) || (((ins)->opcode >= OP_ICEQ) && ((ins)->opcode <= OP_ICLT_UN)) || (((ins)->opcode >= OP_LCEQ) && ((ins)->opcode <= OP_LCLT_UN)) || (((ins)->opcode >= OP_FCEQ) && ((ins)->opcode <= OP_FCLT_UN)))
-#define MONO_IS_LOAD_MEMBASE(ins) (((ins)->opcode >= OP_LOAD_MEMBASE) && ((ins)->opcode <= OP_LOADV_MEMBASE))
-#define MONO_IS_STORE_MEMBASE(ins) (((ins)->opcode >= OP_STORE_MEMBASE_REG) && ((ins)->opcode <= OP_STOREV_MEMBASE))
+#define MONO_IS_LOAD_MEMBASE(ins) (((ins)->opcode >= OP_LOAD_MEMBASE && (ins)->opcode <= OP_LOADV_MEMBASE) || ((ins)->opcode >= OP_ATOMIC_LOAD_I1 && (ins)->opcode <= OP_ATOMIC_LOAD_R8))
+#define MONO_IS_STORE_MEMBASE(ins) (((ins)->opcode >= OP_STORE_MEMBASE_REG && (ins)->opcode <= OP_STOREV_MEMBASE) || ((ins)->opcode >= OP_ATOMIC_STORE_I1 && (ins)->opcode <= OP_ATOMIC_STORE_R8))
#define MONO_IS_STORE_MEMINDEX(ins) (((ins)->opcode >= OP_STORE_MEMINDEX) && ((ins)->opcode <= OP_STORER8_MEMINDEX))
#define MONO_IS_CALL(ins) (((ins->opcode >= OP_VOIDCALL) && (ins->opcode <= OP_VOIDCALL_MEMBASE)) || ((ins->opcode >= OP_FCALL) && (ins->opcode <= OP_FCALL_MEMBASE)) || ((ins->opcode >= OP_LCALL) && (ins->opcode <= OP_LCALL_MEMBASE)) || ((ins->opcode >= OP_VCALL) && (ins->opcode <= OP_VCALL_MEMBASE)) || ((ins->opcode >= OP_CALL) && (ins->opcode <= OP_CALL_MEMBASE)) || ((ins->opcode >= OP_VCALL2) && (ins->opcode <= OP_VCALL2_MEMBASE)) || (ins->opcode == OP_TAILCALL))
/* FIXME: Add more instructions */
/* INEG sets the condition codes, and the OP_LNEG decomposition depends on this on x86 */
-#define MONO_INS_HAS_NO_SIDE_EFFECT(ins) (MONO_IS_MOVE (ins) || (ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || MONO_IS_ZERO (ins) || (ins->opcode == OP_ADD_IMM) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_LADD_IMM) || (ins->opcode == OP_ISUB_IMM) || (ins->opcode == OP_IADD_IMM) || (ins->opcode == OP_LNEG) || (ins->opcode == OP_ISUB) || (ins->opcode == OP_CMOV_IGE) || (ins->opcode == OP_ISHL_IMM) || (ins->opcode == OP_ISHR_IMM) || (ins->opcode == OP_ISHR_UN_IMM) || (ins->opcode == OP_IAND_IMM) || (ins->opcode == OP_ICONV_TO_U1) || (ins->opcode == OP_ICONV_TO_I1) || (ins->opcode == OP_SEXT_I4) || (ins->opcode == OP_LCONV_TO_U1) || (ins->opcode == OP_ICONV_TO_U2) || (ins->opcode == OP_ICONV_TO_I2) || (ins->opcode == OP_LCONV_TO_I2) || (ins->opcode == OP_LDADDR) || (ins->opcode == OP_PHI) || (ins->opcode == OP_NOP) || (ins->opcode == OP_ZEXT_I4) || (ins->opcode == OP_NOT_NULL))
+#define MONO_INS_HAS_NO_SIDE_EFFECT(ins) (MONO_IS_MOVE (ins) || (ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || MONO_IS_ZERO (ins) || (ins->opcode == OP_ADD_IMM) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_LADD_IMM) || (ins->opcode == OP_ISUB_IMM) || (ins->opcode == OP_IADD_IMM) || (ins->opcode == OP_LNEG) || (ins->opcode == OP_ISUB) || (ins->opcode == OP_CMOV_IGE) || (ins->opcode == OP_ISHL_IMM) || (ins->opcode == OP_ISHR_IMM) || (ins->opcode == OP_ISHR_UN_IMM) || (ins->opcode == OP_IAND_IMM) || (ins->opcode == OP_ICONV_TO_U1) || (ins->opcode == OP_ICONV_TO_I1) || (ins->opcode == OP_SEXT_I4) || (ins->opcode == OP_LCONV_TO_U1) || (ins->opcode == OP_ICONV_TO_U2) || (ins->opcode == OP_ICONV_TO_I2) || (ins->opcode == OP_LCONV_TO_I2) || (ins->opcode == OP_LDADDR) || (ins->opcode == OP_PHI) || (ins->opcode == OP_NOP) || (ins->opcode == OP_ZEXT_I4) || (ins->opcode == OP_NOT_NULL) || (ins->opcode == OP_IL_SEQ_POINT))
#define MONO_METHOD_IS_FINAL(m) (((m)->flags & METHOD_ATTRIBUTE_FINAL) || ((m)->klass && ((m)->klass->flags & TYPE_ATTRIBUTE_SEALED)))
LLVMArgVtypeByVal,
LLVMArgVtypeRetAddr, /* On on cinfo->ret */
LLVMArgGSharedVt,
+ /* Vtype passed as one int array argument */
+ LLVMArgAsIArgs,
+ /* Vtype passed as a set of fp arguments */
+ LLVMArgAsFpArgs
} LLVMArgStorage;
typedef struct {
LLVMArgStorage storage;
- /* Only if storage == ArgValuetypeInReg */
- LLVMArgStorage pair_storage [2];
+ /*
+ * Only if storage == ArgValuetypeInReg/LLVMArgAsFpArgs.
+ * This contains how the parts of the vtype are passed.
+ */
+ LLVMArgStorage pair_storage [8];
+ /*
+ * Only if storage == LLVMArgAsIArgs/LLVMArgAsFpArgs.
+ * If storage == LLVMArgAsFpArgs, this is the number of arguments
+ * used to pass the value.
+ */
+ int nslots;
+ /* Only if storage == LLVMArgAsFpArgs (4/8) */
+ int esize;
} LLVMArgInfo;
typedef struct {
MonoInst *spill_var; /* for OP_ICONV_TO_R8_RAW and OP_FCONV_TO_R8_X */
guint16 source_opcode; /*OP_XCONV_R8_TO_I4 needs to know which op was used to do proper widening*/
int pc_offset; /* OP_GC_LIVERANGE_START/END */
- int memory_barrier_kind; /* see mono-memory-model.h for valid values */
+
+ /*
+ * memory_barrier: MONO_MEMORY_BARRIER_{ACQ,REL,SEQ}
+ * atomic_load_*: MONO_MEMORY_BARRIER_{ACQ,SEQ}
+ * atomic_store_*: MONO_MEMORY_BARRIER_{REL,SEQ}
+ */
+ int memory_barrier_kind;
} backend;
MonoClass *klass;
MONO_TRAMPOLINE_RESTORE_STACK_PROT,
MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
MONO_TRAMPOLINE_MONITOR_ENTER,
+ MONO_TRAMPOLINE_MONITOR_ENTER_V4,
MONO_TRAMPOLINE_MONITOR_EXIT,
MONO_TRAMPOLINE_VCALL,
MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD,
(t) == MONO_TRAMPOLINE_RESTORE_STACK_PROT || \
(t) == MONO_TRAMPOLINE_RGCTX_LAZY_FETCH || \
(t) == MONO_TRAMPOLINE_MONITOR_ENTER || \
+ (t) == MONO_TRAMPOLINE_MONITOR_ENTER_V4 || \
(t) == MONO_TRAMPOLINE_MONITOR_EXIT)
/* These trampolines receive an argument directly in a register */
#define MONO_TRAMPOLINE_TYPE_HAS_ARG(t) \
((t) == MONO_TRAMPOLINE_GENERIC_CLASS_INIT || \
(t) == MONO_TRAMPOLINE_MONITOR_ENTER || \
+ (t) == MONO_TRAMPOLINE_MONITOR_ENTER_V4 || \
(t) == MONO_TRAMPOLINE_MONITOR_EXIT || \
(t) == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD)
guint uses_simd_intrinsics : 1;
guint keep_cil_nops : 1;
guint gen_seq_points : 1;
+ guint gen_seq_points_debug_data : 1;
guint explicit_null_checks : 1;
guint compute_gc_maps : 1;
guint soft_breakpoints : 1;
GPtrArray *seq_points;
/* The encoded sequence point info */
- MonoSeqPointInfo *seq_point_info;
+ struct MonoSeqPointInfo *seq_point_info;
/* Method headers which need to be freed after compilation */
GSList *headers_to_free;
/* The offsets of the locals area relative to the frame pointer */
gint locals_min_stack_offset, locals_max_stack_offset;
+ /* The current CFA rule */
+ int cur_cfa_reg, cur_cfa_offset;
+
/* The final CFA rule at the end of the prolog */
int cfa_reg, cfa_offset;
gint32 max_code_size_ratio;
gint32 biggest_method_size;
gint32 allocated_code_size;
+ gint32 allocated_seq_points_size;
gint32 inlineable_methods;
gint32 inlined_methods;
gint32 basic_blocks;
gboolean suspend_on_unhandled;
gboolean dyn_runtime_invoke;
gboolean gdb;
- gboolean gen_seq_points;
+ /*
+ * Whenever data such as next sequence points and flags is required.
+ * Next sequence points and flags are required by the debugger agent.
+ */
+ gboolean gen_seq_points_debug_data;
+ gboolean gen_seq_points_compact_data;
gboolean explicit_null_checks;
/*
* Fill stack frames with 0x2a in method prologs. This helps with the
typedef void (*MonoInstFunc) (MonoInst *tree, gpointer data);
+enum {
+ FILTER_IL_SEQ_POINT = 1 << 0,
+ FILTER_NOP = 1 << 1,
+};
+
+static inline gboolean
+mono_inst_filter (MonoInst *ins, int filter)
+{
+ if (!ins || !filter)
+ return FALSE;
+
+ if ((filter & FILTER_IL_SEQ_POINT) && ins->opcode == OP_IL_SEQ_POINT)
+ return TRUE;
+
+ if ((filter & FILTER_NOP) && ins->opcode == OP_NOP)
+ return TRUE;
+
+ return FALSE;
+}
+
+static inline MonoInst*
+mono_inst_next (MonoInst *ins, int filter)
+{
+ do {
+ ins = ins->next;
+ } while (mono_inst_filter (ins, filter));
+
+ return ins;
+}
+
+static inline MonoInst*
+mono_inst_prev (MonoInst *ins, int filter)
+{
+ do {
+ ins = ins->prev;
+ } while (mono_inst_filter (ins, filter));
+
+ return ins;
+}
+
+static inline MonoInst*
+mono_bb_first_inst (MonoBasicBlock *bb, int filter)
+{
+ MonoInst *ins = bb->code;
+ if (mono_inst_filter (ins, filter))
+ ins = mono_inst_next (ins, filter);
+
+ return ins;
+}
+
+static inline MonoInst*
+mono_bb_last_inst (MonoBasicBlock *bb, int filter)
+{
+ MonoInst *ins = bb->last_ins;
+ if (mono_inst_filter (ins, filter))
+ ins = mono_inst_prev (ins, filter);
+
+ return ins;
+}
+
/* main function */
MONO_API int mono_main (int argc, char* argv[]);
MONO_API void mono_set_defaults (int verbose_level, guint32 opts);
void mono_llvm_cleanup (void) MONO_LLVM_INTERNAL;
void mono_llvm_emit_method (MonoCompile *cfg) MONO_LLVM_INTERNAL;
void mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call) MONO_LLVM_INTERNAL;
-void mono_llvm_create_aot_module (const char *got_symbol) MONO_LLVM_INTERNAL;
-void mono_llvm_emit_aot_module (const char *filename, const char *cu_name, int got_size) MONO_LLVM_INTERNAL;
+void mono_llvm_create_aot_module (const char *got_symbol, gboolean external_symbols, gboolean emit_dwarf) MONO_LLVM_INTERNAL;
+void mono_llvm_emit_aot_module (const char *filename, const char *cu_name) MONO_LLVM_INTERNAL;
void mono_llvm_check_method_supported (MonoCompile *cfg) MONO_LLVM_INTERNAL;
void mono_llvm_free_domain_info (MonoDomain *domain) MONO_LLVM_INTERNAL;
gpointer mono_create_delegate_virtual_trampoline (MonoDomain *domain, MonoClass *klass, MonoMethod *method) MONO_INTERNAL;
gpointer mono_create_rgctx_lazy_fetch_trampoline (guint32 offset) MONO_INTERNAL;
gpointer mono_create_monitor_enter_trampoline (void) MONO_INTERNAL;
+gpointer mono_create_monitor_enter_v4_trampoline (void) MONO_INTERNAL;
gpointer mono_create_monitor_exit_trampoline (void) MONO_INTERNAL;
gpointer mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr) MONO_INTERNAL;
gpointer mono_create_llvm_imt_trampoline (MonoDomain *domain, MonoMethod *m, int vt_offset) MONO_LLVM_INTERNAL;
void mono_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp) MONO_INTERNAL;
void mono_generic_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp) MONO_INTERNAL;
void mono_monitor_enter_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp) MONO_INTERNAL;
+void mono_monitor_enter_v4_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp) MONO_INTERNAL;
void mono_monitor_exit_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp) MONO_INTERNAL;
gconstpointer mono_get_trampoline_func (MonoTrampolineType tramp_type);
gpointer mini_get_vtable_trampoline (int slot_index) MONO_INTERNAL;
+const char* mono_get_generic_trampoline_simple_name (MonoTrampolineType tramp_type) MONO_INTERNAL;
char* mono_get_generic_trampoline_name (MonoTrampolineType tramp_type) MONO_INTERNAL;
char* mono_get_rgctx_fetch_trampoline_name (int slot) MONO_INTERNAL;
gpointer mini_get_nullified_class_init_trampoline (void) MONO_INTERNAL;
gpointer mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_create_generic_class_init_trampoline (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_get_nullified_class_init_trampoline (MonoTrampInfo **info) MONO_INTERNAL;
-gpointer mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
+gpointer mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
guint8 *mono_arch_create_llvm_native_thunk (MonoDomain *domain, guint8* addr) MONO_LLVM_INTERNAL;
GList *mono_arch_get_allocatable_int_vars (MonoCompile *cfg) MONO_INTERNAL;
gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_get_throw_pending_exception (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
gboolean mono_arch_handle_exception (void *sigctx, gpointer obj) MONO_INTERNAL;
-void mono_arch_handle_altstack_exception (void *sigctx, gpointer fault_addr, gboolean stack_ovf) MONO_INTERNAL;
-gboolean mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr) MONO_INTERNAL;
+void mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, gpointer fault_addr, gboolean stack_ovf) MONO_INTERNAL;
+gboolean mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, guint8* fault_addr) MONO_INTERNAL;
void mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr) MONO_INTERNAL;
gpointer mono_arch_ip_from_context (void *sigctx) MONO_INTERNAL;
mgreg_t mono_arch_context_get_int_reg (MonoContext *ctx, int reg) MONO_INTERNAL;
void mono_exceptions_init (void) MONO_INTERNAL;
gboolean mono_handle_exception (MonoContext *ctx, gpointer obj) MONO_INTERNAL;
-void mono_handle_native_sigsegv (int signal, void *sigctx) MONO_INTERNAL;
+void mono_handle_native_sigsegv (int signal, void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo) MONO_INTERNAL;
MONO_API void mono_print_thread_dump (void *sigctx);
MONO_API void mono_print_thread_dump_from_ctx (MonoContext *ctx);
void mono_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data) MONO_INTERNAL;