@@ -368,10 +368,12 @@ typedef struct MonoAotCompile {
368368 MonoDwarfWriter * dwarf ;
369369 FILE * fp ;
370370 char * tmpbasename ;
371- char * tmpfname ;
371+ char * asm_fname ;
372372 char * temp_dir_to_delete ;
373373 char * llvm_sfile ;
374374 char * llvm_ofile ;
375+ char * bc_fname ;
376+ char * optbc_fname ;
375377 GSList * cie_program ;
376378 GHashTable * unwind_info_offsets ;
377379 GPtrArray * unwind_ops ;
@@ -483,9 +485,15 @@ get_patch_name (int info)
483485static int
484486aot_assembly (MonoAssembly * ass , guint32 jit_opts , MonoAotOptions * aot_options );
485487
488+ static void
489+ set_paths (MonoAotCompile * acfg );
490+
486491static int
487492emit_aot_image (MonoAotCompile * acfg );
488493
494+ static int
495+ assemble_link (MonoAotCompile * acfg );
496+
489497static guint32
490498get_unwind_info_offset (MonoAotCompile * acfg , guint8 * encoded , guint32 encoded_len );
491499
@@ -10651,32 +10659,21 @@ execute_system (const char * command)
1065110659#endif
1065210660
1065310661/*
10654- * emit_llvm_file :
10662+ * compile_llvm_file :
1065510663 *
10656- * Emit the LLVM code into an LLVM bytecode file, and compile it using the LLVM
10657- * tools.
10664+ * Compile the llvm bitcode file using the LLVM tools.
1065810665 */
1065910666static gboolean
10660- emit_llvm_file (MonoAotCompile * acfg )
10667+ compile_llvm_file (MonoAotCompile * acfg )
1066110668{
1066210669 char * command , * opts , * tempbc , * optbc , * output_fname ;
1066310670
10664- if (acfg -> aot_opts .llvm_only && acfg -> aot_opts .asm_only ) {
10665- if (acfg -> aot_opts .no_opt )
10666- tempbc = g_strdup (acfg -> aot_opts .llvm_outfile );
10667- else
10668- tempbc = g_strdup_printf ("%s.bc" , acfg -> tmpbasename );
10669- optbc = g_strdup (acfg -> aot_opts .llvm_outfile );
10670- } else {
10671- tempbc = g_strdup_printf ("%s.bc" , acfg -> tmpbasename );
10672- optbc = g_strdup_printf ("%s.opt.bc" , acfg -> tmpbasename );
10673- }
10674-
10675- mono_llvm_emit_aot_module (tempbc , g_path_get_basename (acfg -> image -> name ));
10676-
1067710671 if (acfg -> aot_opts .no_opt )
1067810672 return TRUE;
1067910673
10674+ tempbc = acfg -> bc_fname ;
10675+ optbc = acfg -> optbc_fname ;
10676+
1068010677#if (defined(TARGET_X86 ) || defined(TARGET_AMD64 ))
1068110678 if (acfg -> aot_opts .llvm_cpu_attr && strstr (acfg -> aot_opts .llvm_cpu_attr , "sse4.2" ))
1068210679 /*
@@ -10799,7 +10796,7 @@ emit_llvm_file (MonoAotCompile *acfg)
1079910796#if ( defined(TARGET_MACH ) && defined(TARGET_ARM ) ) || defined(TARGET_ORBIS ) || defined(TARGET_X86_64_WIN32_MSVC ) || defined(TARGET_ANDROID )
1080010797 g_string_append_printf (acfg -> llc_args , " -relocation-model=pic" );
1080110798#else
10802- if (llvm_acfg -> aot_opts .static_link )
10799+ if (acfg -> aot_opts .static_link )
1080310800 g_string_append_printf (acfg -> llc_args , " -relocation-model=static" );
1080410801 else
1080510802 g_string_append_printf (acfg -> llc_args , " -relocation-model=pic" );
@@ -13182,7 +13179,7 @@ compile_asm (MonoAotCompile *acfg)
1318213179#endif
1318313180
1318413181 if (acfg -> aot_opts .asm_only ) {
13185- aot_printf (acfg , "Output file: '%s'.\n" , acfg -> tmpfname );
13182+ aot_printf (acfg , "Output file: '%s'.\n" , acfg -> asm_fname );
1318613183 if (acfg -> aot_opts .static_link )
1318713184 aot_printf (acfg , "Linking symbol: '%s'.\n" , acfg -> static_linking_symbol );
1318813185 if (acfg -> llvm )
@@ -13196,7 +13193,7 @@ compile_asm (MonoAotCompile *acfg)
1319613193 else
1319713194 objfile = g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX , acfg -> image -> name );
1319813195 } else {
13199- objfile = g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX , acfg -> tmpfname );
13196+ objfile = g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX , acfg -> asm_fname );
1320013197 }
1320113198
1320213199#ifdef TARGET_OSX
@@ -13205,7 +13202,7 @@ compile_asm (MonoAotCompile *acfg)
1320513202
1320613203 command = g_strdup_printf ("\"%s%s\" %s %s -o %s %s" , as_prefix , AS_NAME , AS_OPTIONS ,
1320713204 acfg -> as_args ? acfg -> as_args -> str : "" ,
13208- wrap_path (objfile ), wrap_path (acfg -> tmpfname ));
13205+ wrap_path (objfile ), wrap_path (acfg -> asm_fname ));
1320913206 aot_printf (acfg , "Executing the native assembler: %s\n" , command );
1321013207 if (execute_system (command ) != 0 ) {
1321113208 g_free (command );
@@ -13290,7 +13287,7 @@ compile_asm (MonoAotCompile *acfg)
1329013287#endif
1329113288 g_string_append_printf (str , " -o %s %s %s %s" ,
1329213289 wrap_path (tmp_outfile_name ), wrap_path (llvm_ofile ),
13293- wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX , acfg -> tmpfname )), ld_flags );
13290+ wrap_path (g_strdup_printf ("%s." AS_OBJECT_FILE_SUFFIX , acfg -> asm_fname )), ld_flags );
1329413291
1329513292#if defined(TARGET_MACH )
1329613293 g_string_append_printf (str , " \"-Wl,-install_name,%s%s\"" , g_path_get_basename (acfg -> image -> name ), MONO_SOLIB_EXT );
@@ -13357,7 +13354,7 @@ compile_asm (MonoAotCompile *acfg)
1335713354 if (acfg -> aot_opts .save_temps )
1335813355 aot_printf (acfg , "Retained input file.\n" );
1335913356 else
13360- g_unlink (acfg -> tmpfname );
13357+ g_unlink (acfg -> asm_fname );
1336113358
1336213359 return 0 ;
1336313360}
@@ -15052,6 +15049,7 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1505215049 arch_init (acfg );
1505315050
1505415051 if (mono_use_llvm || acfg -> aot_opts .llvm ) {
15052+ acfg -> llvm = TRUE;
1505515053 /*
1505615054 * Emit all LLVM code into a separate assembly/object file and link with it
1505715055 * normally.
@@ -15066,6 +15064,8 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1506615064 }
1506715065 }
1506815066
15067+ set_paths (acfg );
15068+
1506915069 if (acfg -> llvm && acfg -> thumb_mixed )
1507015070 acfg -> flags = (MonoAotFileFlags )(acfg -> flags | MONO_AOT_FILE_FLAG_LLVM_THUMB );
1507115071 if (acfg -> aot_opts .llvm_only )
@@ -15290,24 +15290,18 @@ create_depfile (MonoAotCompile *acfg)
1529015290 fclose (depfile );
1529115291}
1529215292
15293- static int
15294- emit_aot_image (MonoAotCompile * acfg )
15293+ static void
15294+ set_paths (MonoAotCompile * acfg )
1529515295{
15296- int res ;
15297- TV_DECLARE (atv );
15298- TV_DECLARE (btv );
15299-
15300- TV_GETTIME (atv );
15301-
1530215296#ifdef ENABLE_LLVM
1530315297 if (acfg -> llvm ) {
1530415298 if (acfg -> aot_opts .asm_only ) {
1530515299 if (acfg -> aot_opts .outfile ) {
15306- acfg -> tmpfname = g_strdup_printf ("%s" , acfg -> aot_opts .outfile );
15307- acfg -> tmpbasename = g_strdup (acfg -> tmpfname );
15300+ acfg -> asm_fname = g_strdup_printf ("%s" , acfg -> aot_opts .outfile );
15301+ acfg -> tmpbasename = g_strdup (acfg -> asm_fname );
1530815302 } else {
1530915303 acfg -> tmpbasename = g_strdup_printf ("%s" , acfg -> image -> name );
15310- acfg -> tmpfname = g_strdup_printf ("%s.s" , acfg -> tmpbasename );
15304+ acfg -> asm_fname = g_strdup_printf ("%s.s" , acfg -> tmpbasename );
1531115305 }
1531215306 g_assert (acfg -> aot_opts .llvm_outfile );
1531315307 acfg -> llvm_sfile = g_strdup (acfg -> aot_opts .llvm_outfile );
@@ -15326,7 +15320,7 @@ emit_aot_image (MonoAotCompile *acfg)
1532615320 }
1532715321
1532815322 acfg -> tmpbasename = g_build_filename (temp_path , "temp" , (const char * )NULL );
15329- acfg -> tmpfname = g_strdup_printf ("%s.s" , acfg -> tmpbasename );
15323+ acfg -> asm_fname = g_strdup_printf ("%s.s" , acfg -> tmpbasename );
1533015324 acfg -> llvm_sfile = g_strdup_printf ("%s-llvm.s" , acfg -> tmpbasename );
1533115325
1533215326 if (acfg -> aot_opts .static_link )
@@ -15336,26 +15330,88 @@ emit_aot_image (MonoAotCompile *acfg)
1533615330
1533715331 g_free (temp_path );
1533815332 }
15333+
15334+ if (acfg -> aot_opts .llvm_only && acfg -> aot_opts .asm_only ) {
15335+ if (acfg -> aot_opts .no_opt )
15336+ acfg -> bc_fname = g_strdup (acfg -> aot_opts .llvm_outfile );
15337+ else
15338+ acfg -> bc_fname = g_strdup_printf ("%s.bc" , acfg -> tmpbasename );
15339+ acfg -> optbc_fname = g_strdup (acfg -> aot_opts .llvm_outfile );
15340+ } else {
15341+ acfg -> bc_fname = g_strdup_printf ("%s.bc" , acfg -> tmpbasename );
15342+ acfg -> optbc_fname = g_strdup_printf ("%s.opt.bc" , acfg -> tmpbasename );
15343+ }
1533915344 }
1534015345#endif
1534115346
1534215347 if (acfg -> aot_opts .asm_only && !acfg -> aot_opts .llvm_only ) {
1534315348 if (acfg -> aot_opts .outfile )
15344- acfg -> tmpfname = g_strdup_printf ("%s" , acfg -> aot_opts .outfile );
15349+ acfg -> asm_fname = g_strdup_printf ("%s" , acfg -> aot_opts .outfile );
1534515350 else
15346- acfg -> tmpfname = g_strdup_printf ("%s.s" , acfg -> image -> name );
15347- acfg -> fp = g_fopen (acfg -> tmpfname , "w+" );
15351+ acfg -> asm_fname = g_strdup_printf ("%s.s" , acfg -> image -> name );
1534815352 } else {
1534915353 if (strcmp (acfg -> aot_opts .temp_path , "" ) == 0 ) {
15350- acfg -> fp = fdopen ( g_file_open_tmp ( "mono_aot_XXXXXX" , & acfg -> tmpfname , NULL ), "w+" );
15354+ /* Done later */
1535115355 } else {
1535215356 acfg -> tmpbasename = g_build_filename (acfg -> aot_opts .temp_path , "temp" , (const char * )NULL );
15353- acfg -> tmpfname = g_strdup_printf ("%s.s" , acfg -> tmpbasename );
15354- acfg -> fp = g_fopen (acfg -> tmpfname , "w+" );
15357+ acfg -> asm_fname = g_strdup_printf ("%s.s" , acfg -> tmpbasename );
15358+ }
15359+ }
15360+ }
15361+
15362+ /* Run external tools to assemble/link the aot image */
15363+ static int
15364+ assemble_link (MonoAotCompile * acfg )
15365+ {
15366+ int res ;
15367+ TV_DECLARE (atv );
15368+ TV_DECLARE (btv );
15369+
15370+ TV_GETTIME (atv );
15371+
15372+ #ifdef ENABLE_LLVM
15373+ if (acfg -> llvm ) {
15374+ gboolean emit_res ;
15375+
15376+ emit_res = compile_llvm_file (acfg );
15377+ if (!emit_res )
15378+ return 1 ;
15379+ }
15380+ #endif
15381+
15382+ if (!acfg -> aot_opts .llvm_only ) {
15383+ res = compile_asm (acfg );
15384+ if (res != 0 ) {
15385+ acfg_free (acfg );
15386+ return res ;
15387+ }
15388+ }
15389+ TV_GETTIME (btv );
15390+ acfg -> stats .link_time = GINT64_TO_INT (TV_ELAPSED (atv , btv ));
15391+
15392+ return 0 ;
15393+ }
15394+
15395+ static int
15396+ emit_aot_image (MonoAotCompile * acfg )
15397+ {
15398+ int res ;
15399+ TV_DECLARE (atv );
15400+ TV_DECLARE (btv );
15401+
15402+ TV_GETTIME (atv );
15403+
15404+ if (acfg -> aot_opts .asm_only && !acfg -> aot_opts .llvm_only ) {
15405+ acfg -> fp = g_fopen (acfg -> asm_fname , "w+" );
15406+ } else {
15407+ if (strcmp (acfg -> aot_opts .temp_path , "" ) == 0 ) {
15408+ acfg -> fp = fdopen (g_file_open_tmp ("mono_aot_XXXXXX" , & acfg -> asm_fname , NULL ), "w+" );
15409+ } else {
15410+ acfg -> fp = g_fopen (acfg -> asm_fname , "w+" );
1535515411 }
1535615412 }
1535715413 if (acfg -> fp == 0 && !acfg -> aot_opts .llvm_only ) {
15358- aot_printerrf (acfg , "Unable to open file '%s': %s\n" , acfg -> tmpfname , strerror (errno ));
15414+ aot_printerrf (acfg , "Unable to open file '%s': %s\n" , acfg -> asm_fname , strerror (errno ));
1535915415 return 1 ;
1536015416 }
1536115417 if (acfg -> fp )
@@ -15473,13 +15529,8 @@ emit_aot_image (MonoAotCompile *acfg)
1547315529 fclose (acfg -> data_outfile );
1547415530
1547515531#ifdef ENABLE_LLVM
15476- if (acfg -> llvm ) {
15477- gboolean emit_res ;
15478-
15479- emit_res = emit_llvm_file (acfg );
15480- if (!emit_res )
15481- return 1 ;
15482- }
15532+ if (acfg -> llvm )
15533+ mono_llvm_emit_aot_module (acfg -> bc_fname , g_path_get_basename (acfg -> image -> name ));
1548315534#endif
1548415535
1548515536 emit_library_info (acfg );
@@ -15491,33 +15542,29 @@ emit_aot_image (MonoAotCompile *acfg)
1549115542 if (!acfg -> aot_opts .stats )
1549215543 aot_printf (acfg , "Compiled: %d/%d\n" , acfg -> stats .ccount , acfg -> stats .mcount );
1549315544
15494- TV_GETTIME (atv );
1549515545 if (acfg -> w ) {
1549615546 res = mono_img_writer_emit_writeout (acfg -> w );
1549715547 if (res != 0 ) {
1549815548 acfg_free (acfg );
1549915549 return res ;
1550015550 }
15501- res = compile_asm (acfg );
15502- if (res != 0 ) {
15503- acfg_free (acfg );
15504- return res ;
15505- }
1550615551 }
15507- TV_GETTIME (btv );
15508- acfg -> stats .link_time = GINT64_TO_INT (TV_ELAPSED (atv , btv ));
15509-
15510- if (acfg -> aot_opts .stats )
15511- print_stats (acfg );
15512-
15513- aot_printf (acfg , "JIT time: %d ms, Generation time: %d ms, Assembly+Link time: %d ms.\n" , acfg -> stats .jit_time / 1000 , acfg -> stats .gen_time / 1000 , acfg -> stats .link_time / 1000 );
1551415552
1551515553 if (acfg -> aot_opts .depfile )
1551615554 create_depfile (acfg );
1551715555
1551815556 if (acfg -> aot_opts .dump_json )
1551915557 aot_dump (acfg );
1552015558
15559+ res = assemble_link (acfg );
15560+ if (res )
15561+ return res ;
15562+
15563+ if (acfg -> aot_opts .stats )
15564+ print_stats (acfg );
15565+
15566+ aot_printf (acfg , "JIT time: %d ms, Generation time: %d ms, Assembly+Link time: %d ms.\n" , acfg -> stats .jit_time / 1000 , acfg -> stats .gen_time / 1000 , acfg -> stats .link_time / 1000 );
15567+
1552115568 if (!acfg -> aot_opts .save_temps && acfg -> temp_dir_to_delete ) {
1552215569 char * command = g_strdup_printf ("rm -r %s" , acfg -> temp_dir_to_delete );
1552315570 execute_system (command );
0 commit comments