authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-24 18:35:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-24 18:46:32-07:00
log20cc7af8e6e47ba209ab0d462826f40516c86b9d
tree865fcfffdc31cf0b7220d41198266f0627b2d118
parent27c5c7fb23fceb0a333444408a1dea4188a14c32

stage2: support LLD -O flags on ELF

In 7e23b3245a9bf6e002009e6c18c10a9995671afa I made -O flags to the linker emit a warning that the argument does nothing. That was not correct however; LLD does have some logic that does different things depending on -O0, -O1, and -O2. It defaults to -O1, and it does less optimizations with -O0 and more with -O2. With this commit, e.g. `-Wl,-O1` is supported by the `zig cc` frontend, and by default we pass `-O0` to LLD in debug mode, and `-O3` in release modes. I also fixed a bug in the LLD ELF linker line which was incorrectly passing `-O` flags instead of `--lto-O` flags for LTO.

5 files changed, 45 insertions(+), 30 deletions(-)

src/Compilation.zig+6
...@@ -736,6 +736,7 @@ pub const InitOptions = struct {...@@ -736,6 +736,7 @@ pub const InitOptions = struct {
736 linker_tsaware: bool = false,736 linker_tsaware: bool = false,
737 linker_nxcompat: bool = false,737 linker_nxcompat: bool = false,
738 linker_dynamicbase: bool = false,738 linker_dynamicbase: bool = false,
739 linker_optimization: ?u8 = null,
739 major_subsystem_version: ?u32 = null,740 major_subsystem_version: ?u32 = null,
740 minor_subsystem_version: ?u32 = null,741 minor_subsystem_version: ?u32 = null,
741 clang_passthrough_mode: bool = false,742 clang_passthrough_mode: bool = false,
...@@ -1140,6 +1141,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1140,6 +1141,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1140 const strip = options.strip or !target_util.hasDebugInfo(options.target);1141 const strip = options.strip or !target_util.hasDebugInfo(options.target);
1141 const red_zone = options.want_red_zone orelse target_util.hasRedZone(options.target);1142 const red_zone = options.want_red_zone orelse target_util.hasRedZone(options.target);
1142 const omit_frame_pointer = options.omit_frame_pointer orelse (options.optimize_mode != .Debug);1143 const omit_frame_pointer = options.omit_frame_pointer orelse (options.optimize_mode != .Debug);
1144 const linker_optimization: u8 = options.linker_optimization orelse switch (options.optimize_mode) {
1145 .Debug => @as(u8, 0),
1146 else => @as(u8, 3),
1147 };
11431148
1144 // We put everything into the cache hash that *cannot be modified during an incremental update*.1149 // We put everything into the cache hash that *cannot be modified during an incremental update*.
1145 // For example, one cannot change the target between updates, but one can change source files,1150 // For example, one cannot change the target between updates, but one can change source files,
...@@ -1450,6 +1455,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1450,6 +1455,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1450 .tsaware = options.linker_tsaware,1455 .tsaware = options.linker_tsaware,
1451 .nxcompat = options.linker_nxcompat,1456 .nxcompat = options.linker_nxcompat,
1452 .dynamicbase = options.linker_dynamicbase,1457 .dynamicbase = options.linker_dynamicbase,
1458 .linker_optimization = linker_optimization,
1453 .major_subsystem_version = options.major_subsystem_version,1459 .major_subsystem_version = options.major_subsystem_version,
1454 .minor_subsystem_version = options.minor_subsystem_version,1460 .minor_subsystem_version = options.minor_subsystem_version,
1455 .stack_size_override = options.stack_size_override,1461 .stack_size_override = options.stack_size_override,
src/link.zig+1
...@@ -99,6 +99,7 @@ pub const Options = struct {...@@ -99,6 +99,7 @@ pub const Options = struct {
99 tsaware: bool,99 tsaware: bool,
100 nxcompat: bool,100 nxcompat: bool,
101 dynamicbase: bool,101 dynamicbase: bool,
102 linker_optimization: u8,
102 bind_global_refs_locally: bool,103 bind_global_refs_locally: bool,
103 import_memory: bool,104 import_memory: bool,
104 initial_memory: ?u64,105 initial_memory: ?u64,
src/link/Elf.zig+6-2
...@@ -1349,6 +1349,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1349,6 +1349,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1349 man.hash.add(self.base.options.bind_global_refs_locally);1349 man.hash.add(self.base.options.bind_global_refs_locally);
1350 man.hash.add(self.base.options.tsan);1350 man.hash.add(self.base.options.tsan);
1351 man.hash.addOptionalBytes(self.base.options.sysroot);1351 man.hash.addOptionalBytes(self.base.options.sysroot);
1352 man.hash.add(self.base.options.linker_optimization);
13521353
1353 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.1354 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
1354 _ = try man.hit();1355 _ = try man.hit();
...@@ -1425,10 +1426,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1425,10 +1426,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1425 if (self.base.options.lto) {1426 if (self.base.options.lto) {
1426 switch (self.base.options.optimize_mode) {1427 switch (self.base.options.optimize_mode) {
1427 .Debug => {},1428 .Debug => {},
1428 .ReleaseSmall => try argv.append("-O2"),1429 .ReleaseSmall => try argv.append("--lto-O2"),
1429 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),1430 .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"),
1430 }1431 }
1431 }1432 }
1433 try argv.append(try std.fmt.allocPrint(arena, "-O{d}", .{
1434 self.base.options.linker_optimization,
1435 }));
14321436
1433 if (self.base.options.output_mode == .Exe) {1437 if (self.base.options.output_mode == .Exe) {
1434 try argv.append("-z");1438 try argv.append("-z");
src/main.zig+8-4
...@@ -635,6 +635,7 @@ fn buildOutputType(...@@ -635,6 +635,7 @@ fn buildOutputType(
635 var linker_tsaware = false;635 var linker_tsaware = false;
636 var linker_nxcompat = false;636 var linker_nxcompat = false;
637 var linker_dynamicbase = false;637 var linker_dynamicbase = false;
638 var linker_optimization: ?u8 = null;
638 var test_evented_io = false;639 var test_evented_io = false;
639 var test_no_exec = false;640 var test_no_exec = false;
640 var stack_size_override: ?u64 = null;641 var stack_size_override: ?u64 = null;
...@@ -1488,11 +1489,13 @@ fn buildOutputType(...@@ -1488,11 +1489,13 @@ fn buildOutputType(
1488 if (i >= linker_args.items.len) {1489 if (i >= linker_args.items.len) {
1489 fatal("expected linker arg after '{s}'", .{arg});1490 fatal("expected linker arg after '{s}'", .{arg});
1490 }1491 }
1491 warn("ignoring linker arg -O{s} because it does nothing", .{1492 linker_optimization = std.fmt.parseUnsigned(u8, linker_args.items[i], 10) catch |err| {
1492 linker_args.items[i],1493 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1493 });1494 };
1494 } else if (mem.startsWith(u8, arg, "-O")) {1495 } else if (mem.startsWith(u8, arg, "-O")) {
1495 warn("ignoring linker arg {s} because it does nothing", .{arg});1496 linker_optimization = std.fmt.parseUnsigned(u8, arg["-O".len..], 10) catch |err| {
1497 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1498 };
1496 } else if (mem.eql(u8, arg, "--gc-sections")) {1499 } else if (mem.eql(u8, arg, "--gc-sections")) {
1497 linker_gc_sections = true;1500 linker_gc_sections = true;
1498 } else if (mem.eql(u8, arg, "--no-gc-sections")) {1501 } else if (mem.eql(u8, arg, "--no-gc-sections")) {
...@@ -2309,6 +2312,7 @@ fn buildOutputType(...@@ -2309,6 +2312,7 @@ fn buildOutputType(
2309 .linker_tsaware = linker_tsaware,2312 .linker_tsaware = linker_tsaware,
2310 .linker_nxcompat = linker_nxcompat,2313 .linker_nxcompat = linker_nxcompat,
2311 .linker_dynamicbase = linker_dynamicbase,2314 .linker_dynamicbase = linker_dynamicbase,
2315 .linker_optimization = linker_optimization,
2312 .major_subsystem_version = major_subsystem_version,2316 .major_subsystem_version = major_subsystem_version,
2313 .minor_subsystem_version = minor_subsystem_version,2317 .minor_subsystem_version = minor_subsystem_version,
2314 .link_eh_frame_hdr = link_eh_frame_hdr,2318 .link_eh_frame_hdr = link_eh_frame_hdr,
test/standalone/install_raw_hex/build.zig+24-24
...@@ -35,7 +35,7 @@ pub fn build(b: *Builder) void {...@@ -35,7 +35,7 @@ pub fn build(b: *Builder) void {
35 ":1001140000000000000000000000000000000000DB",35 ":1001140000000000000000000000000000000000DB",
36 ":1001240000000000000000000000000000000000CB",36 ":1001240000000000000000000000000000000000CB",
37 ":1001340000000000000000000000000000000000BB",37 ":1001340000000000000000000000000000000000BB",
38 ":10014400830202006C020100090000002102010088",38 ":1001440083020200F401010009000000FE01010025",
39 ":100154000900000001000000000000000000000091",39 ":100154000900000001000000000000000000000091",
40 ":1001640000080002008001010004000010000000EB",40 ":1001640000080002008001010004000010000000EB",
41 ":100174000000000000000000000000001F0000005C",41 ":100174000000000000000000000000001F0000005C",
...@@ -44,17 +44,17 @@ pub fn build(b: *Builder) void {...@@ -44,17 +44,17 @@ pub fn build(b: *Builder) void {
44 ":1001A40000000000000000001F000000000000002C",44 ":1001A40000000000000000001F000000000000002C",
45 ":1001B400000000000000000000000000000000003B",45 ":1001B400000000000000000000000000000000003B",
46 ":1001C400000000000000000000000000000000002B",46 ":1001C400000000000000000000000000000000002B",
47 ":1001D4005B02010010000000F40101002C0000008B",47 ":1001D4000802010010000000190201002C000000B8",
48 ":1001E4003F0201001B0000002B020100130000006D",48 ":1001E400460201001B00000062020100130000002F",
49 ":1001F40072656D61696E646572206469766973699C",49 ":1001F400636F727465785F6D3400636F72746578D1",
50 ":100204006F6E206279207A65726F206F72206E653E",50 ":100204002D6D34006469766973696F6E206279209C",
51 ":100214006761746976652076616C756500636F72D9",51 ":100214007A65726F0072656D61696E6465722064DF",
52 ":100224007465782D6D3400696E646578206F75741B",52 ":1002240069766973696F6E206279207A65726F20CE",
53 ":10023400206F6620626F756E647300696E74656703",53 ":100234006F72206E656761746976652076616C758E",
54 ":1002440065722063617374207472756E6361746582",54 ":100244006500696E746567657220636173742074F8",
55 ":10025400642062697473006469766973696F6E20DF",55 ":1002540072756E6361746564206269747300696E9B",
56 ":100264006279207A65726F00636F727465785F6D6E",56 ":10026400646578206F7574206F6620626F756E64A4",
57 ":100274003400000081B00091FFE700BEFDE7D0B577",57 ":100274007300000081B00091FFE700BEFDE7D0B538",
58 ":1002840002AF90B00391029007A800F029F80399F7",58 ":1002840002AF90B00391029007A800F029F80399F7",
59 ":100294000020069048680490FFE7049906980190AE",59 ":100294000020069048680490FFE7049906980190AE",
60 ":1002A40088420FD2FFE7019903980068405C07F881",60 ":1002A40088420FD2FFE7019903980068405C07F881",
...@@ -89,7 +89,7 @@ pub fn build(b: *Builder) void {...@@ -89,7 +89,7 @@ pub fn build(b: *Builder) void {
89 ":1001140000000000000000000000000000000000DB",89 ":1001140000000000000000000000000000000000DB",
90 ":1001240000000000000000000000000000000000CB",90 ":1001240000000000000000000000000000000000CB",
91 ":1001340000000000000000000000000000000000BB",91 ":1001340000000000000000000000000000000000BB",
92 ":10014400830202006C020100090000002102010088",92 ":1001440083020200F401010009000000FE01010025",
93 ":100154000900000001000000000000000000000091",93 ":100154000900000001000000000000000000000091",
94 ":1001640000080002008001010004000010000000EB",94 ":1001640000080002008001010004000010000000EB",
95 ":100174000000000000000000000000001F0000005C",95 ":100174000000000000000000000000001F0000005C",
...@@ -98,17 +98,17 @@ pub fn build(b: *Builder) void {...@@ -98,17 +98,17 @@ pub fn build(b: *Builder) void {
98 ":1001A40000000000000000001F000000000000002C",98 ":1001A40000000000000000001F000000000000002C",
99 ":1001B400000000000000000000000000000000003B",99 ":1001B400000000000000000000000000000000003B",
100 ":1001C400000000000000000000000000000000002B",100 ":1001C400000000000000000000000000000000002B",
101 ":1001D4005B02010010000000F40101002C0000008B",101 ":1001D4000802010010000000190201002C000000B8",
102 ":1001E4003F0201001B0000002B020100130000006D",102 ":1001E400460201001B00000062020100130000002F",
103 ":1001F40072656D61696E646572206469766973699C",103 ":1001F400636F727465785F6D3400636F72746578D1",
104 ":100204006F6E206279207A65726F206F72206E653E",104 ":100204002D6D34006469766973696F6E206279209C",
105 ":100214006761746976652076616C756500636F72D9",105 ":100214007A65726F0072656D61696E6465722064DF",
106 ":100224007465782D6D3400696E646578206F75741B",106 ":1002240069766973696F6E206279207A65726F20CE",
107 ":10023400206F6620626F756E647300696E74656703",107 ":100234006F72206E656761746976652076616C758E",
108 ":1002440065722063617374207472756E6361746582",108 ":100244006500696E746567657220636173742074F8",
109 ":10025400642062697473006469766973696F6E20DF",109 ":1002540072756E6361746564206269747300696E9B",
110 ":100264006279207A65726F00636F727465785F6D6E",110 ":10026400646578206F7574206F6620626F756E64A4",
111 ":100274003400000081B00091FFE700BEFDE7D0B577",111 ":100274007300000081B00091FFE700BEFDE7D0B538",
112 ":1002840002AF90B00391029007A800F029F80399F7",112 ":1002840002AF90B00391029007A800F029F80399F7",
113 ":100294000020069048680490FFE7049906980190AE",113 ":100294000020069048680490FFE7049906980190AE",
114 ":1002A40088420FD2FFE7019903980068405C07F881",114 ":1002A40088420FD2FFE7019903980068405C07F881",