@@ -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}
@@ -14831,6 +14828,11 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1483114828 dedup_change_phase (acfg , DEDUP_EMIT );
1483214829 }
1483314830
14831+ if (mono_use_llvm || acfg -> aot_opts .llvm )
14832+ acfg -> llvm = TRUE;
14833+
14834+ set_paths (acfg );
14835+
1483414836 if (acfg -> aot_opts .logfile ) {
1483514837 acfg -> logfile = g_fopen (acfg -> aot_opts .logfile , "a+" );
1483614838 }
@@ -15290,24 +15292,18 @@ create_depfile (MonoAotCompile *acfg)
1529015292 fclose (depfile );
1529115293}
1529215294
15293- static int
15294- emit_aot_image (MonoAotCompile * acfg )
15295+ static void
15296+ set_paths (MonoAotCompile * acfg )
1529515297{
15296- int res ;
15297- TV_DECLARE (atv );
15298- TV_DECLARE (btv );
15299-
15300- TV_GETTIME (atv );
15301-
1530215298#ifdef ENABLE_LLVM
1530315299 if (acfg -> llvm ) {
1530415300 if (acfg -> aot_opts .asm_only ) {
1530515301 if (acfg -> aot_opts .outfile ) {
15306- acfg -> tmpfname = g_strdup_printf ("%s" , acfg -> aot_opts .outfile );
15307- acfg -> tmpbasename = g_strdup (acfg -> tmpfname );
15302+ acfg -> asm_fname = g_strdup_printf ("%s" , acfg -> aot_opts .outfile );
15303+ acfg -> tmpbasename = g_strdup (acfg -> asm_fname );
1530815304 } else {
1530915305 acfg -> tmpbasename = g_strdup_printf ("%s" , acfg -> image -> name );
15310- acfg -> tmpfname = g_strdup_printf ("%s.s" , acfg -> tmpbasename );
15306+ acfg -> asm_fname = g_strdup_printf ("%s.s" , acfg -> tmpbasename );
1531115307 }
1531215308 g_assert (acfg -> aot_opts .llvm_outfile );
1531315309 acfg -> llvm_sfile = g_strdup (acfg -> aot_opts .llvm_outfile );
@@ -15326,7 +15322,7 @@ emit_aot_image (MonoAotCompile *acfg)
1532615322 }
1532715323
1532815324 acfg -> tmpbasename = g_build_filename (temp_path , "temp" , (const char * )NULL );
15329- acfg -> tmpfname = g_strdup_printf ("%s.s" , acfg -> tmpbasename );
15325+ acfg -> asm_fname = g_strdup_printf ("%s.s" , acfg -> tmpbasename );
1533015326 acfg -> llvm_sfile = g_strdup_printf ("%s-llvm.s" , acfg -> tmpbasename );
1533115327
1533215328 if (acfg -> aot_opts .static_link )
@@ -15336,26 +15332,88 @@ emit_aot_image (MonoAotCompile *acfg)
1533615332
1533715333 g_free (temp_path );
1533815334 }
15335+
15336+ if (acfg -> aot_opts .llvm_only && acfg -> aot_opts .asm_only ) {
15337+ if (acfg -> aot_opts .no_opt )
15338+ acfg -> bc_fname = g_strdup (acfg -> aot_opts .llvm_outfile );
15339+ else
15340+ acfg -> bc_fname = g_strdup_printf ("%s.bc" , acfg -> tmpbasename );
15341+ acfg -> optbc_fname = g_strdup (acfg -> aot_opts .llvm_outfile );
15342+ } else {
15343+ acfg -> bc_fname = g_strdup_printf ("%s.bc" , acfg -> tmpbasename );
15344+ acfg -> optbc_fname = g_strdup_printf ("%s.opt.bc" , acfg -> tmpbasename );
15345+ }
1533915346 }
1534015347#endif
1534115348
1534215349 if (acfg -> aot_opts .asm_only && !acfg -> aot_opts .llvm_only ) {
1534315350 if (acfg -> aot_opts .outfile )
15344- acfg -> tmpfname = g_strdup_printf ("%s" , acfg -> aot_opts .outfile );
15351+ acfg -> asm_fname = g_strdup_printf ("%s" , acfg -> aot_opts .outfile );
1534515352 else
15346- acfg -> tmpfname = g_strdup_printf ("%s.s" , acfg -> image -> name );
15347- acfg -> fp = g_fopen (acfg -> tmpfname , "w+" );
15353+ acfg -> asm_fname = g_strdup_printf ("%s.s" , acfg -> image -> name );
1534815354 } else {
1534915355 if (strcmp (acfg -> aot_opts .temp_path , "" ) == 0 ) {
15350- acfg -> fp = fdopen ( g_file_open_tmp ( "mono_aot_XXXXXX" , & acfg -> tmpfname , NULL ), "w+" );
15356+ /* Done later */
1535115357 } else {
1535215358 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+" );
15359+ acfg -> asm_fname = g_strdup_printf ("%s.s" , acfg -> tmpbasename );
15360+ }
15361+ }
15362+ }
15363+
15364+ /* Run external tools to assemble/link the aot image */
15365+ static int
15366+ assemble_link (MonoAotCompile * acfg )
15367+ {
15368+ int res ;
15369+ TV_DECLARE (atv );
15370+ TV_DECLARE (btv );
15371+
15372+ TV_GETTIME (atv );
15373+
15374+ #ifdef ENABLE_LLVM
15375+ if (acfg -> llvm ) {
15376+ gboolean emit_res ;
15377+
15378+ emit_res = compile_llvm_file (acfg );
15379+ if (!emit_res )
15380+ return 1 ;
15381+ }
15382+ #endif
15383+
15384+ if (!acfg -> aot_opts .llvm_only ) {
15385+ res = compile_asm (acfg );
15386+ if (res != 0 ) {
15387+ acfg_free (acfg );
15388+ return res ;
15389+ }
15390+ }
15391+ TV_GETTIME (btv );
15392+ acfg -> stats .link_time = GINT64_TO_INT (TV_ELAPSED (atv , btv ));
15393+
15394+ return 0 ;
15395+ }
15396+
15397+ static int
15398+ emit_aot_image (MonoAotCompile * acfg )
15399+ {
15400+ int res ;
15401+ TV_DECLARE (atv );
15402+ TV_DECLARE (btv );
15403+
15404+ TV_GETTIME (atv );
15405+
15406+ if (acfg -> aot_opts .asm_only && !acfg -> aot_opts .llvm_only ) {
15407+ acfg -> fp = g_fopen (acfg -> asm_fname , "w+" );
15408+ } else {
15409+ if (strcmp (acfg -> aot_opts .temp_path , "" ) == 0 ) {
15410+ acfg -> fp = fdopen (g_file_open_tmp ("mono_aot_XXXXXX" , & acfg -> asm_fname , NULL ), "w+" );
15411+ } else {
15412+ acfg -> fp = g_fopen (acfg -> asm_fname , "w+" );
1535515413 }
1535615414 }
1535715415 if (acfg -> fp == 0 && !acfg -> aot_opts .llvm_only ) {
15358- aot_printerrf (acfg , "Unable to open file '%s': %s\n" , acfg -> tmpfname , strerror (errno ));
15416+ aot_printerrf (acfg , "Unable to open file '%s': %s\n" , acfg -> asm_fname , strerror (errno ));
1535915417 return 1 ;
1536015418 }
1536115419 if (acfg -> fp )
@@ -15473,13 +15531,8 @@ emit_aot_image (MonoAotCompile *acfg)
1547315531 fclose (acfg -> data_outfile );
1547415532
1547515533#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- }
15534+ if (acfg -> llvm )
15535+ mono_llvm_emit_aot_module (acfg -> bc_fname , g_path_get_basename (acfg -> image -> name ));
1548315536#endif
1548415537
1548515538 emit_library_info (acfg );
@@ -15491,33 +15544,29 @@ emit_aot_image (MonoAotCompile *acfg)
1549115544 if (!acfg -> aot_opts .stats )
1549215545 aot_printf (acfg , "Compiled: %d/%d\n" , acfg -> stats .ccount , acfg -> stats .mcount );
1549315546
15494- TV_GETTIME (atv );
1549515547 if (acfg -> w ) {
1549615548 res = mono_img_writer_emit_writeout (acfg -> w );
1549715549 if (res != 0 ) {
1549815550 acfg_free (acfg );
1549915551 return res ;
1550015552 }
15501- res = compile_asm (acfg );
15502- if (res != 0 ) {
15503- acfg_free (acfg );
15504- return res ;
15505- }
1550615553 }
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 );
1551415554
1551515555 if (acfg -> aot_opts .depfile )
1551615556 create_depfile (acfg );
1551715557
1551815558 if (acfg -> aot_opts .dump_json )
1551915559 aot_dump (acfg );
1552015560
15561+ res = assemble_link (acfg );
15562+ if (res )
15563+ return res ;
15564+
15565+ if (acfg -> aot_opts .stats )
15566+ print_stats (acfg );
15567+
15568+ 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 );
15569+
1552115570 if (!acfg -> aot_opts .save_temps && acfg -> temp_dir_to_delete ) {
1552215571 char * command = g_strdup_printf ("rm -r %s" , acfg -> temp_dir_to_delete );
1552315572 execute_system (command );
0 commit comments