2006-06-04 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini.h
index decc48ba48af227b184fda6721bbad37a3c23534..81d75262b92c817fd572ce94c3488cace20b75dc 100644 (file)
 #include "regalloc.h"
 #include "declsec.h"
 
+#ifndef G_LIKELY
+#define G_LIKELY(a) (a)
+#define G_UNLIKELY(a) (a)
+#endif
+
+#if DISABLE_LOGGING
+#define MINI_DEBUG(level,limit,code)
+#else
+#define MINI_DEBUG(level,limit,code) do {if (G_UNLIKELY ((level) >= (limit))) code} while (0)
+#endif
+
+#ifndef DISABLE_AOT
 #define MONO_USE_AOT_COMPILER
+#endif
 
 /* for 32 bit systems */
 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
 #define inst_ms_word data.op[0].const_val
 #endif
 
-#if SIZEOF_VOID_P == 8
-#define OP_PCONST OP_I8CONST
-#else
-#define OP_PCONST OP_ICONST
-#endif
-
 /* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION "20"
-
-#if 1
-#define mono_bitset_test_fast(set,n) (((guint32*)set)[2+(n)/32] & (1 << ((n) % 32)))
-#else
-#define mono_bitset_test_fast(set,n) mono_bitset_test(set,n)
-#endif
+#define MONO_AOT_FILE_VERSION "27"
 
 #if 0
 #define mono_bitset_foreach_bit(set,b,n) \
@@ -60,7 +61,7 @@
                if (mono_bitset_test_fast(set,b))
 #else
 #define mono_bitset_foreach_bit(set,b,n) \
-       for (b = mono_bitset_find_first (set, -1); b < n && b >= 0; b = mono_bitset_find_first (set, b))
+       for (b = mono_bitset_find_start (set); b < n && b >= 0; b = mono_bitset_find_first (set, b))
 #define mono_bitset_foreach_bit_rev(set,b,n) \
        for (b = mono_bitset_find_last (set, n - 1); b >= 0; b = b ? mono_bitset_find_last (set, b) : -1)
  
@@ -90,6 +91,11 @@ enum {
                (dest)->inst.opcode = (op);     \
        } while (0)
 
+#define MONO_INST_NEW_CALL_ARG(cfg,dest,op) do {       \
+               (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoCallArgParm));        \
+               (dest)->ins.opcode = (op);      \
+       } while (0)
+
 #define MONO_ADD_INS(b,inst) do {      \
                if ((b)->last_ins) {    \
                        (b)->last_ins->next = (inst);   \
@@ -101,6 +107,7 @@ enum {
 
 typedef struct MonoInst MonoInst;
 typedef struct MonoCallInst MonoCallInst;
+typedef struct MonoCallArgParm MonoCallArgParm;
 typedef struct MonoEdge MonoEdge;
 typedef struct MonoMethodVar MonoMethodVar;
 typedef struct MonoBasicBlock MonoBasicBlock;
@@ -126,7 +133,9 @@ struct MonoEdge {
 };
 
 struct MonoSpillInfo {
+#ifndef MONO_ARCH_HAS_XP_REGALLOC
        MonoSpillInfo *next;
+#endif
        int offset;
 };
 
@@ -143,6 +152,28 @@ struct MonoSpillInfo {
 struct MonoBasicBlock {
        MonoInst *last_ins;
 
+       /* the next basic block in the order it appears in IL */
+       MonoBasicBlock *next_bb;
+
+       /*
+        * Before instruction selection it is the first tree in the
+        * forest and the first item in the list of trees. After
+        * instruction selection it is the first instruction and the
+        * first item in the list of instructions.
+        */
+       MonoInst *code;
+
+       /* unique block number identification */
+       gint32 block_num;
+       
+       gint32 dfn;
+
+       /* Basic blocks: incoming and outgoing counts and pointers */
+       /* Each bb should only appear once in each array */
+       gint16 out_count, in_count;
+       MonoBasicBlock **in_bb;
+       MonoBasicBlock **out_bb;
+
        /* Points to the start of the CIL code that initiated this BB */
        unsigned char* cil_code;
 
@@ -152,31 +183,10 @@ struct MonoBasicBlock {
        /* The address of the generated code, used for fixups */
        int native_offset;
        int max_offset;
-       
-       gint32 dfn;
-
-       /* unique block number identification */
-       gint32 block_num;
 
        /* Visited and reachable flags */
        guint32 flags;
 
-       /* Basic blocks: incoming and outgoing counts and pointers */
-       gint16 out_count, in_count;
-       MonoBasicBlock **in_bb;
-       MonoBasicBlock **out_bb;
-
-       /* the next basic block in the order it appears in IL */
-       MonoBasicBlock *next_bb;
-
-       /*
-        * Before instruction selection it is the first tree in the
-        * forest and the first item in the list of trees. After
-        * instruction selection it is the first instruction and the
-        * first item in the list of instructions.
-        */
-       MonoInst *code;
-
        /*
         * SSA and loop based flags
         */
@@ -198,7 +208,9 @@ struct MonoBasicBlock {
         * Whenever the bblock is rarely executed so it should be emitted after
         * the function epilog.
         */
-       gboolean out_of_line;
+       guint out_of_line : 1;
+       /* Caches the result of uselessness calculation during optimize_branches */
+       guint not_useless : 1;
 
        /* use for liveness analysis */
        MonoBitSet *gen_set;
@@ -234,8 +246,13 @@ struct MonoBasicBlock {
 };
 
 /* BBlock flags */
-#define BB_VISITED 1
-#define BB_REACHABLE 2
+enum {
+       BB_VISITED            = 1 << 0,
+       BB_REACHABLE          = 1 << 1,
+       BB_EXCEPTION_DEAD_OBJ = 1 << 2,
+       BB_EXCEPTION_UNSAFE   = 1 << 3,
+       BB_EXCEPTION_HANDLER  = 1 << 4
+};
 
 struct MonoInst {
        union {
@@ -280,12 +297,19 @@ struct MonoCallInst {
        gboolean virtual;
        regmask_t used_iregs;
        regmask_t used_fregs;
-#if defined(MONO_ARCH_HAS_XP_LOCAL_REGALLOC) || defined(__x86_64__)
+#if defined(MONO_ARCH_HAS_XP_LOCAL_REGALLOC)
        GSList *out_ireg_args;
        GSList *out_freg_args;
 #endif
 };
 
+struct MonoCallArgParm {
+       MonoInst ins;
+       gint32 size;
+       gint32 offset;
+       gint32 offPrm;
+};
+
 /* 
  * flags for MonoInst
  * Note: some of the values overlap, because they can't appear
@@ -415,6 +439,7 @@ typedef enum {
        MONO_PATCH_INFO_R8,
        MONO_PATCH_INFO_IP,
        MONO_PATCH_INFO_IID,
+       MONO_PATCH_INFO_ADJUSTED_IID,
        MONO_PATCH_INFO_BB_OVF,
        MONO_PATCH_INFO_EXC_OVF,
        MONO_PATCH_INFO_WRAPPER,
@@ -473,6 +498,8 @@ typedef enum {
        MONO_TRAMPOLINE_JUMP,
        MONO_TRAMPOLINE_CLASS_INIT,
        MONO_TRAMPOLINE_AOT,
+       MONO_TRAMPOLINE_AOT_PLT,
+       MONO_TRAMPOLINE_DELEGATE,
        MONO_TRAMPOLINE_NUM
 } MonoTrampolineType;
 
@@ -497,7 +524,10 @@ enum {
        MONO_OPT_AOT      = 1 << 16,
        MONO_OPT_PRECOMP  = 1 << 17,
        MONO_OPT_ABCREM   = 1 << 18,
-       MONO_OPT_SSAPRE   = 1 << 19
+       MONO_OPT_SSAPRE   = 1 << 19,
+       MONO_OPT_EXCEPTION= 1 << 20,
+       MONO_OPT_SSA      = 1 << 21,
+       MONO_OPT_TREEPROP = 1 << 22
 };
 
 /* Bit-fields in the MonoBasicBlock.region */
@@ -539,10 +569,13 @@ typedef struct {
        MonoSpillInfo   *spill_info; /* machine register spills */
        MonoSpillInfo   *spill_info_float; /* fp register spills */
        gint             spill_count;
+       gint             spill_info_len, spill_info_float_len;
        /* unsigned char   *cil_code; */
        MonoMethod      *inlined_method; /* the method which is currently inlined */
        MonoInst        *domainvar; /* a cache for the current domain */
        MonoInst        *got_var; /* Global Offset Table variable */
+       
+       struct MonoAliasingInformation *aliasing_info;
 
        /* A hashtable of region ID-> SP var mappings */
        /* An SP var is a place to store the stack pointer (used by handlers)*/
@@ -571,13 +604,13 @@ typedef struct {
        guint32          param_area;
        guint32          frame_reg;
        gint32           sig_cookie;
-       gboolean         disable_aot;
-       gboolean         disable_ssa;
-       gboolean         run_cctors;
-       gboolean         need_lmf_area;
-       gboolean         compile_aot;
-       gboolean         got_var_allocated;
-       gboolean         ret_var_is_local;
+       guint            disable_aot : 1;
+       guint            disable_ssa : 1;
+       guint            run_cctors : 1;
+       guint            need_lmf_area : 1;
+       guint            compile_aot : 1;
+       guint            got_var_allocated : 1;
+       guint            ret_var_is_local : 1;
        gpointer         debug_info;
        guint32          lmf_offset;
        guint16          *intvars;
@@ -586,9 +619,13 @@ typedef struct {
        guint32          exception_type;        /* MONO_EXCEPTION_* */
        guint32          exception_data;
        char*            exception_message;
-#ifdef __ia64
-       guint8           ins, locals, outs; /* reg stack region sizes */
-#endif /* __ia64 */
+
+       /* Fields used by the local reg allocator */
+       void*            reginfo;
+       void*            reginfof;
+       void*            reverse_inst_list;
+       int              reginfo_len, reginfof_len;
+       int              reverse_inst_list_len;
 } MonoCompile;
 
 typedef enum {
@@ -596,7 +633,9 @@ typedef enum {
        MONO_CFG_HAS_CALLS  = 1 << 1,
        MONO_CFG_HAS_LDELEMA  = 1 << 2,
        MONO_CFG_HAS_VARARGS  = 1 << 3,
-       MONO_CFG_HAS_TAIL     = 1 << 4
+       MONO_CFG_HAS_TAIL     = 1 << 4,
+       MONO_CFG_HAS_FPOUT    = 1 << 5, /* there are fp values passed in int registers */
+       MONO_CFG_HAS_SPILLUP  = 1 << 6  /* spill var slots are allocated from bottom to top */
 } MonoCompileFlags;
 
 typedef struct {
@@ -631,11 +670,15 @@ extern MonoJitStats mono_jit_stats;
 
 /* values for MonoInst.ssa_op */
 enum {
-       MONO_SSA_NOP,
-       MONO_SSA_LOAD,
-       MONO_SSA_STORE,
-       MONO_SSA_MAYBE_LOAD,
-       MONO_SSA_MAYBE_STORE
+       MONO_SSA_NOP = 0,
+       MONO_SSA_ADDRESS_TAKEN = 1,
+       MONO_SSA_LOAD = 2,
+       MONO_SSA_STORE = 4,
+       MONO_SSA_LOAD_STORE = MONO_SSA_LOAD|MONO_SSA_STORE,
+       MONO_SSA_INDIRECT_LOAD = MONO_SSA_LOAD|MONO_SSA_ADDRESS_TAKEN,
+       MONO_SSA_INDIRECT_STORE = MONO_SSA_STORE|MONO_SSA_ADDRESS_TAKEN,
+       MONO_SSA_INDIRECT_LOAD_STORE =
+       MONO_SSA_LOAD|MONO_SSA_STORE|MONO_SSA_ADDRESS_TAKEN
 };
 
 #define OP_CEQ    (256+CEE_CEQ)
@@ -658,6 +701,7 @@ enum {
 #undef MINI_OP
 
 #if SIZEOF_VOID_P == 8
+#define OP_PCONST OP_I8CONST
 #define OP_PADD OP_LADD
 #define OP_PNEG OP_LNEG
 #define OP_PCONV_TO_U2 OP_LCONV_TO_U2
@@ -667,6 +711,7 @@ enum {
 #define OP_STOREP_MEMBASE_REG OP_STOREI8_MEMBASE_REG
 #define OP_STOREP_MEMBASE_IMM OP_STOREI8_MEMBASE_IMM
 #else
+#define OP_PCONST OP_ICONST
 #define OP_PADD CEE_ADD
 #define OP_PNEG CEE_NEG
 #define OP_PCONV_TO_U2 CEE_CONV_U2
@@ -700,6 +745,12 @@ typedef struct {
        int type;
 } StackSlot;
 
+#if HAVE_ARRAY_ELEM_INIT
+extern const guint8 mono_burg_arity [];
+#else
+extern guint8 mono_burg_arity [];
+#endif
+
 enum {
        MONO_COMP_DOM = 1,
        MONO_COMP_IDOM = 2,
@@ -729,7 +780,7 @@ typedef struct {
 typedef struct {
        gboolean handle_sigint;
        gboolean keep_delegates;
-       gboolean abort_on_sigsegv;
+       gboolean collect_pagefault_stats;
 } MonoDebugOptions;
 
 enum {
@@ -779,12 +830,11 @@ void      mono_print_tree                   (MonoInst *tree);
 void      mono_print_tree_nl                (MonoInst *tree);
 void      mono_print_code                   (MonoCompile *cfg);
 void      mono_print_method_from_ip         (void *ip);
+char     *mono_pmip                         (void *ip);
 void      mono_select_instructions          (MonoCompile *cfg);
 const char* mono_inst_name                  (int op);
 void      mono_inst_foreach                 (MonoInst *tree, MonoInstFunc func, gpointer data);
-void      mono_disassemble_code             (guint8 *code, int size, char *id);
-guint     mono_type_to_ldind                (MonoType *t);
-guint     mono_type_to_stind                (MonoType *t);
+void      mono_disassemble_code             (MonoCompile *cfg, guint8 *code, int size, char *id);
 void      mono_add_patch_info               (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target);
 void      mono_remove_patch_info            (MonoCompile *cfg, int ip);
 gpointer  mono_resolve_patch_target         (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors);
@@ -800,18 +850,32 @@ void      mono_create_jump_table            (MonoCompile *cfg, MonoInst *label,
 int       mono_compile_assembly             (MonoAssembly *ass, guint32 opts, const char *aot_options);
 MonoCompile *mini_method_compile            (MonoMethod *method, guint32 opts, MonoDomain *domain, gboolean run_cctors, gboolean compile_aot, int parts);
 void      mono_destroy_compile              (MonoCompile *cfg);
+MonoJitICallInfo *mono_find_jit_opcode_emulation (int opcode);
+
+
 void      mono_aot_init                     (void);
 MonoJitInfo*  mono_aot_get_method           (MonoDomain *domain,
                                                                                         MonoMethod *method);
+gpointer  mono_aot_get_method_from_token    (MonoDomain *domain, MonoImage *image, guint32 token);
 gboolean  mono_aot_is_got_entry             (guint8 *code, guint8 *addr);
+guint8*   mono_aot_get_plt_entry            (guint8 *code);
 gboolean  mono_aot_init_vtable              (MonoVTable *vtable);
 gboolean  mono_aot_get_cached_class_info    (MonoClass *klass, MonoCachedClassInfo *res);
+MonoJitInfo* mono_aot_find_jit_info         (MonoDomain *domain, MonoImage *image, gpointer addr);
+void mono_aot_set_make_unreadable           (gboolean unreadable);
+gboolean mono_aot_is_pagefault              (void *ptr);
+void mono_aot_handle_pagefault              (void *ptr);
+guint32 mono_aot_get_n_pagefaults           (void);
+gpointer mono_aot_plt_resolve               (gpointer aot_module, guint32 plt_info_offset, guint8 *code);
+
 gboolean  mono_method_blittable             (MonoMethod *method);
 gboolean  mono_method_same_domain           (MonoJitInfo *caller, MonoJitInfo *callee);
-void      mono_register_opcode_emulation    (int opcode, const char* name, MonoMethodSignature *sig, gpointer func, gboolean no_throw);
+
+void      mono_register_opcode_emulation    (int opcode, const char* name, const char *sigstr, gpointer func, gboolean no_throw);
 void      mono_draw_graph                   (MonoCompile *cfg, MonoGraphOptions draw_options);
 void      mono_add_varcopy_to_end           (MonoCompile *cfg, MonoBasicBlock *bb, int src, int dest);
 void      mono_add_ins_to_end               (MonoBasicBlock *bb, MonoInst *inst);
+gpointer  mono_create_ftnptr                (MonoDomain *domain, gpointer addr);
 
 int               mono_find_method_opcode      (MonoMethod *method);
 MonoJitICallInfo *mono_find_jit_icall_by_name  (const char *name);
@@ -827,12 +891,21 @@ gpointer          mono_create_class_init_trampoline (MonoVTable *vtable);
 gpointer          mono_create_jit_trampoline (MonoMethod *method);
 gpointer          mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token);
 MonoVTable*       mono_find_class_init_trampoline_by_addr (gconstpointer addr);
+gpointer          mono_magic_trampoline (gssize *regs, guint8 *code, MonoMethod *m, guint8* tramp);
+gpointer          mono_delegate_trampoline (gssize *regs, guint8 *code, MonoMethod *m, guint8* tramp);
+gpointer          mono_aot_trampoline (gssize *regs, guint8 *code, guint8 *token_info, 
+                                                                          guint8* tramp);
+gpointer          mono_aot_plt_trampoline (gssize *regs, guint8 *code, guint8 *token_info, 
+                                                                                  guint8* tramp);
+void              mono_class_init_trampoline (gssize *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp);
 
 gboolean          mono_running_on_valgrind (void);
 void*             mono_global_codeman_reserve (int size);
 const char       *mono_regname_full (int reg, gboolean fp);
+gint32*           mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align);
 gint32*           mono_allocate_stack_slots (MonoCompile *cfg, guint32 *stack_size, guint32 *stack_align);
 void              mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb);
+MonoInst         *mono_branch_optimize_exception_target (MonoCompile *cfg, MonoBasicBlock *bb, const char * exname);             
 
 /* methods that must be provided by the arch-specific port */
 void      mono_arch_cpu_init                    (void);
@@ -841,9 +914,9 @@ void      mono_arch_instrument_mem_needs        (MonoMethod *method, int *stack,
 void     *mono_arch_instrument_prolog           (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments);
 void     *mono_arch_instrument_epilog           (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments);
 MonoCallInst *mono_arch_call_opcode             (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call, int is_virtual);
-MonoInst *mono_arch_get_inst_for_method       (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
+MonoInst *mono_arch_get_inst_for_method         (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
 void      mono_codegen                          (MonoCompile *cfg);
-void      mono_call_inst_add_outarg_reg         (MonoCallInst *call, int vreg, int hreg, gboolean fp);
+void      mono_call_inst_add_outarg_reg         (MonoCompile *cfg, MonoCallInst *call, int vreg, int hreg, gboolean fp);
 const char *mono_arch_regname                   (int reg);
 const char *mono_arch_fregname                  (int reg);
 gpointer  mono_arch_get_throw_exception         (void);
@@ -852,7 +925,6 @@ gpointer  mono_arch_get_throw_exception_by_name (void);
 gpointer  mono_arch_get_throw_corlib_exception  (void);
 guchar*   mono_arch_create_trampoline_code      (MonoTrampolineType tramp_type);
 gpointer  mono_arch_create_jit_trampoline       (MonoMethod *method);
-gpointer  mono_arch_create_jit_trampoline_from_token (MonoImage *image, guint32 token);
 MonoJitInfo *mono_arch_create_jump_trampoline      (MonoMethod *method);
 gpointer  mono_arch_create_class_init_trampoline(MonoVTable *vtable);
 GList    *mono_arch_get_allocatable_int_vars    (MonoCompile *cfg);
@@ -901,11 +973,23 @@ gpointer*mono_arch_get_delegate_method_ptr_addr (guint8* code, gpointer *regs);
 void     mono_arch_create_vars                  (MonoCompile *cfg);
 void     mono_arch_save_unwind_info             (MonoCompile *cfg);
 void     mono_arch_register_lowlevel_calls      (void);
+gpointer mono_arch_get_unbox_trampoline         (MonoMethod *m, gpointer addr);
+void     mono_arch_patch_callsite               (guint8 *code, guint8 *addr);
+void     mono_arch_patch_plt_entry              (guint8 *code, guint8 *addr);
+void     mono_arch_nullify_class_init_trampoline(guint8 *code, gssize *regs);
+void     mono_arch_nullify_plt_entry            (guint8 *code);
+void     mono_arch_patch_delegate_trampoline    (guint8 *code, guint8 *tramp, gssize *regs, guint8 *addr);
+gpointer mono_arch_create_specific_trampoline   (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len);
 
 /* Exception handling */
 gboolean mono_handle_exception                  (MonoContext *ctx, gpointer obj,
                                                 gpointer original_ip, gboolean test_only);
-void      mono_jit_walk_stack                   (MonoStackWalk func, gboolean do_il_offset, gpointer user_data);
+void     mono_handle_native_sigsegv             (int signal, void *sigctx);
+void     mono_print_thread_dump                 (void *sigctx);
+void     mono_jit_walk_stack                    (MonoStackWalk func, gboolean do_il_offset, gpointer user_data);
+void     mono_jit_walk_stack_from_ctx           (MonoStackWalk func, MonoContext *ctx, gboolean do_il_offset, gpointer user_data);
+void     mono_setup_altstack                    (MonoJitTlsData *tls);
+void     mono_free_altstack                     (MonoJitTlsData *tls);
 
 /* the new function to do stack walks */
 typedef gboolean (*MonoStackFrameWalk)          (MonoDomain *domain, MonoContext *ctx, MonoJitInfo *ji, gpointer data);
@@ -938,9 +1022,14 @@ void      mono_debug_open_block                 (MonoCompile *cfg, MonoBasicBloc
 void      mono_debug_record_line_number         (MonoCompile *cfg, MonoInst *ins, guint32 address);
 void      mono_debug_serialize_debug_info       (MonoCompile *cfg, guint8 **out_buf, guint32 *buf_len);
 void      mono_debug_add_aot_method             (MonoDomain *domain,
-                                                                                               MonoMethod *method, guint8 *code_start, 
-                                                                                               guint8 *debug_info, guint32 debug_info_len);
+                                                MonoMethod *method, guint8 *code_start, 
+                                                guint8 *debug_info, guint32 debug_info_len);
 void      mono_debug_add_icall_wrapper          (MonoMethod *method, MonoJitICallInfo* info);
+void      mono_debugger_run_finally             (MonoContext *start_ctx);
+
+/* Mono Debugger support */
+void      mono_debugger_init                    (void);
+int       mono_debugger_main                    (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv);
 
 
 /* Tracing */
@@ -952,6 +1041,8 @@ extern void
 mono_perform_abc_removal (MonoCompile *cfg);
 extern void
 mono_perform_ssapre (MonoCompile *cfg);
+extern void
+mono_local_cprop (MonoCompile *cfg);
 
 /* CAS - stack walk */
 MonoSecurityFrame* ves_icall_System_Security_SecurityFrame_GetSecurityFrame (gint32 skip);