@@ -444,6 +444,7 @@ pub const InitOptions = struct {
444
444
want_valgrind : ? bool = null ,
445
445
want_tsan : ? bool = null ,
446
446
want_compiler_rt : ? bool = null ,
447
+ want_lto : ? bool = null ,
447
448
use_llvm : ? bool = null ,
448
449
use_lld : ? bool = null ,
449
450
use_clang : ? bool = null ,
@@ -602,6 +603,12 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
602
603
if (ofmt == .c )
603
604
break :blk false ;
604
605
606
+ if (options .want_lto ) | lto | {
607
+ if (lto ) {
608
+ break :blk true ;
609
+ }
610
+ }
611
+
605
612
// Our linker can't handle objects or most advanced options yet.
606
613
if (options .link_objects .len != 0 or
607
614
options .c_source_files .len != 0 or
@@ -647,6 +654,26 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
647
654
break :outer opts ;
648
655
} else .{};
649
656
657
+ const lto = blk : {
658
+ if (options .want_lto ) | explicit | {
659
+ if (! use_lld )
660
+ return error .LtoUnavailableWithoutLld ;
661
+ break :blk explicit ;
662
+ } else if (! use_lld ) {
663
+ break :blk false ;
664
+ } else if (options .c_source_files .len == 0 ) {
665
+ break :blk false ;
666
+ } else if (darwin_options .system_linker_hack ) {
667
+ break :blk false ;
668
+ } else switch (options .output_mode ) {
669
+ .Lib , .Obj = > break :blk false ,
670
+ .Exe = > switch (options .optimize_mode ) {
671
+ .Debug = > break :blk false ,
672
+ .ReleaseSafe , .ReleaseFast , .ReleaseSmall = > break :blk true ,
673
+ },
674
+ }
675
+ };
676
+
650
677
const tsan = options .want_tsan orelse false ;
651
678
652
679
const link_libc = options .link_libc or target_util .osRequiresLibC (options .target ) or tsan ;
@@ -821,6 +848,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
821
848
cache .hash .add (ofmt );
822
849
cache .hash .add (pic );
823
850
cache .hash .add (pie );
851
+ cache .hash .add (lto );
824
852
cache .hash .add (tsan );
825
853
cache .hash .add (stack_check );
826
854
cache .hash .add (red_zone );
@@ -1022,6 +1050,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1022
1050
.libc_installation = libc_dirs .libc_installation ,
1023
1051
.pic = pic ,
1024
1052
.pie = pie ,
1053
+ .lto = lto ,
1025
1054
.valgrind = valgrind ,
1026
1055
.tsan = tsan ,
1027
1056
.stack_check = stack_check ,
@@ -2233,6 +2262,9 @@ pub fn addCCArgs(
2233
2262
"-nostdinc" ,
2234
2263
"-fno-spell-checking" ,
2235
2264
});
2265
+ if (comp .bin_file .options .lto ) {
2266
+ try argv .append ("-flto" );
2267
+ }
2236
2268
2237
2269
// According to Rich Felker libc headers are supposed to go before C language headers.
2238
2270
// However as noted by @dimenus, appending libc headers before c_headers breaks intrinsics
@@ -3255,6 +3287,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
3255
3287
.err_color = @enumToInt (comp .color ),
3256
3288
.pic = comp .bin_file .options .pic ,
3257
3289
.pie = comp .bin_file .options .pie ,
3290
+ .lto = comp .bin_file .options .lto ,
3258
3291
.link_libc = comp .bin_file .options .link_libc ,
3259
3292
.link_libcpp = comp .bin_file .options .link_libcpp ,
3260
3293
.strip = comp .bin_file .options .strip ,
@@ -3415,6 +3448,10 @@ pub fn build_crt_file(
3415
3448
.want_tsan = false ,
3416
3449
.want_pic = comp .bin_file .options .pic ,
3417
3450
.want_pie = comp .bin_file .options .pie ,
3451
+ .want_lto = switch (output_mode ) {
3452
+ .Lib = > comp .bin_file .options .lto ,
3453
+ .Obj , .Exe = > false ,
3454
+ },
3418
3455
.emit_h = null ,
3419
3456
.strip = comp .compilerRtStrip (),
3420
3457
.is_native_os = comp .bin_file .options .is_native_os ,
0 commit comments