X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Faot-compiler.c;h=86ebb1dc28df93339857ebb631dc80d704447865;hb=b97dfc8909e6d324f20277f81e7362149cd731d4;hp=01e0eb95a3c6f5581ab46203a0ce817d29b27c33;hpb=d717176fd5f731e064c0fe311bba2ed46f18b5d7;p=mono.git diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 01e0eb95a3c..86ebb1dc28d 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -68,7 +68,7 @@ #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT) -#if defined(__linux__) +#if defined(__linux__) || defined(__native_client_codegen__) #define RODATA_SECT ".rodata" #else #define RODATA_SECT ".text" @@ -330,6 +330,14 @@ emit_byte (MonoAotCompile *acfg, guint8 val) img_writer_emit_byte (acfg->w, val); } +#ifdef __native_client_codegen__ +static inline void +emit_nacl_call_alignment (MonoAotCompile *acfg) +{ + img_writer_emit_nacl_call_alignment (acfg->w); +} +#endif + static G_GNUC_UNUSED void emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func) { @@ -460,6 +468,10 @@ encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf) #else #define AOT_FUNC_ALIGNMENT 16 #endif +#if defined(TARGET_X86) && defined(__native_client_codegen__) +#undef AOT_FUNC_ALIGNMENT +#define AOT_FUNC_ALIGNMENT 32 +#endif #if defined(TARGET_POWERPC64) && !defined(__mono_ilp32__) #define PPC_LD_OP "ld" @@ -654,12 +666,26 @@ arch_emit_plt_entry (MonoAotCompile *acfg, int index) #if defined(TARGET_X86) guint32 offset = (acfg->plt_got_offset_base + index) * sizeof (gpointer); +#ifdef __native_client_codegen__ + const guint8 kSizeOfNaClJmp = 11; + guint8 bytes[kSizeOfNaClJmp]; + guint8 *pbytes = &bytes[0]; + + x86_jump_membase32 (pbytes, X86_EBX, offset); + emit_bytes (acfg, bytes, kSizeOfNaClJmp); + /* four bytes of data, used by mono_arch_patch_plt_entry */ + /* For Native Client, make this work with data embedded in push. */ + emit_byte (acfg, 0x68); /* hide data in a push */ + emit_int32 (acfg, acfg->plt_got_info_offsets [index]); + emit_alignment (acfg, AOT_FUNC_ALIGNMENT); +#else /* jmp *(%ebx) */ emit_byte (acfg, 0xff); emit_byte (acfg, 0xa3); emit_int32 (acfg, offset); /* Used by mono_aot_get_plt_info_offset */ emit_int32 (acfg, acfg->plt_got_info_offsets [index]); +#endif /* __native_client_codegen__ */ #elif defined(TARGET_AMD64) /* * We can't emit jumps because they are 32 bits only so they can't be patched. @@ -846,9 +872,16 @@ arch_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size /* Branch to generic trampoline */ x86_jump_reg (code, X86_ECX); +#ifdef __native_client_codegen__ + { + /* emit nops to next 32 byte alignment */ + int a = (~kNaClAlignmentMask) & ((code - buf) + kNaClAlignment - 1); + while (code < (buf + a)) x86_nop(code); + } +#endif emit_bytes (acfg, buf, code - buf); - *tramp_size = 17; + *tramp_size = NACL_SIZE(17, kNaClAlignment); g_assert (code - buf == *tramp_size); #else g_assert_not_reached (); @@ -882,9 +915,6 @@ arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoMethod *method, MonoGeneri guint8 *code; int this_pos = 4; - if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret)) - this_pos = 8; - code = buf; x86_alu_membase_imm (code, X86_ADD, X86_ESP, this_pos, sizeof (MonoObject)); @@ -897,14 +927,10 @@ arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoMethod *method, MonoGeneri #elif defined(TARGET_ARM) guint8 buf [128]; guint8 *code; - int this_pos = 0; code = buf; - if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret)) - this_pos = 1; - - ARM_ADD_REG_IMM8 (code, this_pos, this_pos, sizeof (MonoObject)); + ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (MonoObject)); emit_bytes (acfg, buf, code - buf); /* jump to method */ @@ -923,9 +949,6 @@ arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoMethod *method, MonoGeneri #elif defined(TARGET_POWERPC) int this_pos = 3; - if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret)) - this_pos = 4; - g_assert (!acfg->use_bin_writer); fprintf (acfg->fp, "\n\taddi %d, %d, %d\n", this_pos, this_pos, (int)sizeof (MonoObject)); @@ -1038,9 +1061,17 @@ arch_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_ /* Branch to the target address */ x86_jump_membase (code, X86_ECX, (offset + 1) * sizeof (gpointer)); +#ifdef __native_client_codegen__ + { + /* emit nops to next 32 byte alignment */ + int a = (~kNaClAlignmentMask) & ((code - buf) + kNaClAlignment - 1); + while (code < (buf + a)) x86_nop(code); + } +#endif + emit_bytes (acfg, buf, code - buf); - *tramp_size = 15; + *tramp_size = NACL_SIZE (15, kNaClAlignment); g_assert (code - buf == *tramp_size); #else g_assert_not_reached (); @@ -1070,36 +1101,38 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size) /* FIXME: Optimize this, i.e. use binary search etc. */ /* Maybe move the body into a separate function (slower, but much smaller) */ - /* R10 is a free register */ + /* R11 is a free register */ labels [0] = code; - amd64_alu_membase_imm (code, X86_CMP, AMD64_R10, 0, 0); + amd64_alu_membase_imm (code, X86_CMP, AMD64_R11, 0, 0); labels [1] = code; amd64_branch8 (code, X86_CC_Z, FALSE, 0); /* Check key */ - amd64_alu_membase_reg (code, X86_CMP, AMD64_R10, 0, MONO_ARCH_IMT_REG); + amd64_alu_membase_reg (code, X86_CMP, AMD64_R11, 0, MONO_ARCH_IMT_REG); labels [2] = code; amd64_branch8 (code, X86_CC_Z, FALSE, 0); /* Loop footer */ - amd64_alu_reg_imm (code, X86_ADD, AMD64_R10, 2 * sizeof (gpointer)); + amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, 2 * sizeof (gpointer)); amd64_jump_code (code, labels [0]); /* Match */ mono_amd64_patch (labels [2], code); - amd64_mov_reg_membase (code, AMD64_R10, AMD64_R10, sizeof (gpointer), 8); - amd64_jump_membase (code, AMD64_R10, 0); + amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, sizeof (gpointer), 8); + amd64_jump_membase (code, AMD64_R11, 0); /* No match */ /* FIXME: */ mono_amd64_patch (labels [1], code); x86_breakpoint (code); - /* mov (%rip), %r10 */ + amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 12345678, 8); + + /* mov (%rip), %r11 */ emit_byte (acfg, '\x4d'); emit_byte (acfg, '\x8b'); - emit_byte (acfg, '\x15'); + emit_byte (acfg, '\x1d'); emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) - 4); emit_bytes (acfg, buf, code - buf); @@ -1107,9 +1140,17 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size) *tramp_size = code - buf + 7; #elif defined(TARGET_X86) guint8 *buf, *code; +#ifdef __native_client_codegen__ + guint8 *buf_alloc; +#endif guint8 *labels [3]; +#ifdef __native_client_codegen__ + buf_alloc = g_malloc (256 + kNaClAlignment); + code = buf = ((guint)buf_alloc + kNaClAlignment) & ~kNaClAlignmentMask; +#else code = buf = g_malloc (256); +#endif /* Allocate a temporary stack slot */ x86_push_reg (code, X86_EAX); @@ -1151,6 +1192,13 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size) mono_x86_patch (labels [1], code); x86_breakpoint (code); +#ifdef __native_client_codegen__ + { + /* emit nops to next 32 byte alignment */ + int a = (~kNaClAlignmentMask) & ((code - buf) + kNaClAlignment - 1); + while (code < (buf + a)) x86_nop(code); + } +#endif emit_bytes (acfg, buf, code - buf); *tramp_size = code - buf; @@ -1425,7 +1473,7 @@ add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len) * blob where the data was stored. */ static guint32 -add_to_blob (MonoAotCompile *acfg, guint8 *data, guint32 data_len) +add_to_blob (MonoAotCompile *acfg, const guint8 *data, guint32 data_len) { if (acfg->blob.alloc_size == 0) stream_init (&acfg->blob); @@ -1732,6 +1780,7 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 case MONO_WRAPPER_ALLOC: { AllocatorWrapperInfo *info = mono_marshal_get_wrapper_info (method); + /* The GC name is saved once in MonoAotFileInfo */ g_assert (info->alloc_type != -1); encode_value (info->alloc_type, p, &p); break; @@ -3082,7 +3131,7 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg) method = cfg->orig_method; code = cfg->native_code; - header = mono_method_get_header (method); + header = cfg->header; method_index = get_method_index (acfg, method); @@ -3416,7 +3465,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) method = cfg->orig_method; code = cfg->native_code; - header = mono_method_get_header (method); + header = cfg->header; method_index = get_method_index (acfg, method); @@ -3463,6 +3512,11 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) /* Exception table */ if (cfg->compile_llvm) { + /* + * When using LLVM, we can't emit some data, like pc offsets, this reg/offset etc., + * since the information is only available to llc. Instead, we let llc save the data + * into the LSDA, and read it from there at runtime. + */ /* The assembly might be CIL stripped so emit the data ourselves */ if (header->num_clauses) encode_value (header->num_clauses, p, &p); @@ -3479,6 +3533,18 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) } else { encode_value (0, p, &p); } + + /* Emit a list of nesting clauses */ + for (i = 0; i < header->num_clauses; ++i) { + gint32 cindex1 = k; + MonoExceptionClause *clause1 = &header->clauses [cindex1]; + gint32 cindex2 = i; + MonoExceptionClause *clause2 = &header->clauses [cindex2]; + + if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) + encode_value (i, p, &p); + } + encode_value (-1, p, &p); } } else { if (jinfo->num_clauses) @@ -3510,9 +3576,11 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) if (jinfo->has_generic_jit_info) { MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (jinfo); - encode_value (gi->has_this ? 1 : 0, p, &p); - encode_value (gi->this_reg, p, &p); - encode_value (gi->this_offset, p, &p); + if (!cfg->compile_llvm) { + encode_value (gi->has_this ? 1 : 0, p, &p); + encode_value (gi->this_reg, p, &p); + encode_value (gi->this_offset, p, &p); + } /* * Need to encode jinfo->method too, since it is not equal to 'method' @@ -3579,8 +3647,19 @@ emit_klass_info (MonoAotCompile *acfg, guint32 token) gboolean no_special_static, cant_encode; gpointer iter = NULL; - if (!klass) - return add_to_blob (acfg, NULL, 0); + if (!klass) { + buf_size = 16; + + p = buf = g_malloc (buf_size); + + /* Mark as unusable */ + encode_value (-1, p, &p); + + res = add_to_blob (acfg, buf, p - buf); + g_free (buf); + + return res; + } buf_size = 10240 + (klass->vtable_size * 16); p = buf = g_malloc (buf_size); @@ -3783,13 +3862,17 @@ emit_trampoline (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info) ji = info->ji; unwind_ops = info->unwind_ops; +#ifdef __native_client_codegen__ + mono_nacl_fix_patches (code, ji); +#endif + /* Emit code */ sprintf (start_symbol, "%s", name); emit_section_change (acfg, ".text", 0); emit_global (acfg, start_symbol, TRUE); - emit_alignment (acfg, 16); + emit_alignment (acfg, AOT_FUNC_ALIGNMENT); emit_label (acfg, start_symbol); sprintf (symbol, "%snamed_%s", acfg->temp_prefix, name); @@ -3988,7 +4071,7 @@ emit_trampolines (MonoAotCompile *acfg) } emit_global (acfg, symbol, TRUE); - emit_alignment (acfg, 16); + emit_alignment (acfg, AOT_FUNC_ALIGNMENT); emit_label (acfg, symbol); acfg->trampoline_got_offset_base [ntype] = tramp_got_offset; @@ -4012,6 +4095,10 @@ emit_trampolines (MonoAotCompile *acfg) default: g_assert_not_reached (); } +#ifdef __native_client_codegen__ + /* align to avoid 32-byte boundary crossings */ + emit_alignment (acfg, AOT_FUNC_ALIGNMENT); +#endif if (!acfg->trampoline_size [ntype]) { g_assert (tramp_size); @@ -4686,12 +4773,13 @@ emit_llvm_file (MonoAotCompile *acfg) * a lot of time, and doesn't seem to save much space. * The following optimizations cannot be enabled: * - 'tailcallelim' + * - 'jump-threading' changes our blockaddress references to int constants. * The opt list below was produced by taking the output of: * llvm-as < /dev/null | opt -O2 -disable-output -debug-pass=Arguments * then removing tailcallelim + the global opts, and adding a second gvn. */ opts = g_strdup ("-instcombine -simplifycfg"); - opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -jump-threading -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loopsimplify -domfrontier -loopsimplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loopsimplify -lcssa -iv-users -indvars -loop-deletion -loopsimplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -jump-threading -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify"); + opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loopsimplify -domfrontier -loopsimplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loopsimplify -lcssa -iv-users -indvars -loop-deletion -loopsimplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify"); #if 1 command = g_strdup_printf ("opt -f %s -o temp.opt.bc temp.bc", opts); printf ("Executing opt: %s\n", command); @@ -4787,6 +4875,9 @@ emit_code (MonoAotCompile *acfg) } emit_section_change (acfg, ".text", 0); +#ifdef __native_client_codegen__ + emit_alignment (acfg, AOT_FUNC_ALIGNMENT); +#endif emit_global (acfg, symbol, TRUE); emit_label (acfg, symbol); @@ -5093,7 +5184,7 @@ emit_extra_methods (MonoAotCompile *acfg) if (!cfg) continue; - buf_size = 1024; + buf_size = 10240; p = buf = g_malloc (buf_size); nmethods ++; @@ -5659,7 +5750,7 @@ emit_globals (MonoAotCompile *acfg) * Emit a global symbol which can be passed by an embedding app to * mono_aot_register_module (). */ -#if defined(__MACH__) +#if defined(__MACH__) && !defined(__native_client_codegen__) sprintf (symbol, "_mono_aot_module_%s_info", acfg->image->assembly->aname.name); #else sprintf (symbol, "mono_aot_module_%s_info", acfg->image->assembly->aname.name); @@ -5719,6 +5810,15 @@ emit_file_info (MonoAotCompile *acfg) { char symbol [128]; int i; + int gc_name_offset; + const char *gc_name; + + /* + * The managed allocators are GC specific, so can't use an AOT image created by one GC + * in another. + */ + gc_name = mono_gc_get_gc_name (); + gc_name_offset = add_to_blob (acfg, (guint8*)gc_name, strlen (gc_name) + 1); sprintf (symbol, "mono_aot_file_info"); emit_section_change (acfg, ".data", 0); @@ -5726,13 +5826,14 @@ emit_file_info (MonoAotCompile *acfg) emit_label (acfg, symbol); emit_global (acfg, symbol, FALSE); - /* The data emitted here must match MonoAotFileInfo in aot-runtime.c. */ + /* The data emitted here must match MonoAotFileInfo. */ emit_int32 (acfg, acfg->plt_got_offset_base); emit_int32 (acfg, (int)(acfg->got_offset * sizeof (gpointer))); emit_int32 (acfg, acfg->plt_offset); emit_int32 (acfg, acfg->nmethods); emit_int32 (acfg, acfg->flags); emit_int32 (acfg, acfg->opts); + emit_int32 (acfg, gc_name_offset); for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i) emit_int32 (acfg, acfg->num_trampolines [i]); @@ -5915,6 +6016,12 @@ compile_asm (MonoAotCompile *acfg) #define AS_OPTIONS "" #endif +#ifdef __native_client_codegen__ +#define AS_NAME "nacl-as" +#else +#define AS_NAME "as" +#endif + #ifndef LD_OPTIONS #define LD_OPTIONS "" #endif @@ -5940,7 +6047,7 @@ compile_asm (MonoAotCompile *acfg) } else { objfile = g_strdup_printf ("%s.o", acfg->tmpfname); } - command = g_strdup_printf ("%sas %s %s -o %s", tool_prefix, AS_OPTIONS, acfg->tmpfname, objfile); + command = g_strdup_printf ("%s%s %s %s -o %s", tool_prefix, AS_NAME, AS_OPTIONS, acfg->tmpfname, objfile); printf ("Executing the native assembler: %s\n", command); if (system (command) != 0) { g_free (command);