authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-24 07:36:21-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-07-24 07:36:21-07:00
log75cf7fca900766713597d21d141292b3725aac50
tree7c95e5dd446d8864053f0f366695c75e6af9a2b0
parent1e74904aa27da423bcfe804a9b06fe8c0a0620ba
parent26d2a7960e9199989d9387e0af29497581422f93
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20767 from ziglang/emit-options

add "trace pc guard" as optional additional coverage instrumentation

11 files changed, 235 insertions(+), 102 deletions(-)

lib/std/Build/Step/Compile.zig+9
...@@ -217,6 +217,14 @@ no_builtin: bool = false,...@@ -217,6 +217,14 @@ no_builtin: bool = false,
217/// Managed by the build runner, not user build script.217/// Managed by the build runner, not user build script.
218zig_process: ?*Step.ZigProcess,218zig_process: ?*Step.ZigProcess,
219219
220/// Enables deprecated coverage instrumentation that is only useful if you
221/// are using third party fuzzers that depend on it. Otherwise, slows down
222/// the instrumented binary with unnecessary function calls.
223///
224/// To enable fuzz testing instrumentation on a compilation, see the `fuzz`
225/// flag in `Module`.
226sanitize_coverage_trace_pc_guard: ?bool = null,
227
220pub const ExpectedCompileErrors = union(enum) {228pub const ExpectedCompileErrors = union(enum) {
221 contains: []const u8,229 contains: []const u8,
222 exact: []const []const u8,230 exact: []const []const u8,
...@@ -1656,6 +1664,7 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {...@@ -1656,6 +1664,7 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {
16561664
1657 try addFlag(&zig_args, "PIE", compile.pie);1665 try addFlag(&zig_args, "PIE", compile.pie);
1658 try addFlag(&zig_args, "lto", compile.want_lto);1666 try addFlag(&zig_args, "lto", compile.want_lto);
1667 try addFlag(&zig_args, "sanitize-coverage-trace-pc-guard", compile.sanitize_coverage_trace_pc_guard);
16591668
1660 if (compile.subsystem) |subsystem| {1669 if (compile.subsystem) |subsystem| {
1661 try zig_args.append("--subsystem");1670 try zig_args.append("--subsystem");
src/Compilation.zig+5
...@@ -1412,6 +1412,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1412,6 +1412,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1412 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);1412 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);
1413 cache.hash.addBytes(options.root_name);1413 cache.hash.addBytes(options.root_name);
1414 cache.hash.add(options.config.wasi_exec_model);1414 cache.hash.add(options.config.wasi_exec_model);
1415 cache.hash.add(options.config.san_cov_trace_pc_guard);
1415 // TODO audit this and make sure everything is in it1416 // TODO audit this and make sure everything is in it
14161417
1417 const main_mod = options.main_mod orelse options.root_mod;1418 const main_mod = options.main_mod orelse options.root_mod;
...@@ -5652,6 +5653,10 @@ pub fn addCCArgs(...@@ -5652,6 +5653,10 @@ pub fn addCCArgs(
5652 // function was called.5653 // function was called.
5653 try argv.append("-fno-sanitize=function");5654 try argv.append("-fno-sanitize=function");
5654 }5655 }
5656
5657 if (comp.config.san_cov_trace_pc_guard) {
5658 try argv.appendSlice(&.{ "-Xclang", "-fsanitize-coverage-trace-pc-guard" });
5659 }
5655 }5660 }
5656 }5661 }
56575662
src/Compilation/Config.zig+3
...@@ -60,6 +60,7 @@ root_strip: bool,...@@ -60,6 +60,7 @@ root_strip: bool,
60root_error_tracing: bool,60root_error_tracing: bool,
61dll_export_fns: bool,61dll_export_fns: bool,
62rdynamic: bool,62rdynamic: bool,
63san_cov_trace_pc_guard: bool,
6364
64pub const CFrontend = enum { clang, aro };65pub const CFrontend = enum { clang, aro };
6566
...@@ -108,6 +109,7 @@ pub const Options = struct {...@@ -108,6 +109,7 @@ pub const Options = struct {
108 debug_format: ?DebugFormat = null,109 debug_format: ?DebugFormat = null,
109 dll_export_fns: ?bool = null,110 dll_export_fns: ?bool = null,
110 rdynamic: ?bool = null,111 rdynamic: ?bool = null,
112 san_cov_trace_pc_guard: bool = false,
111};113};
112114
113pub const ResolveError = error{115pub const ResolveError = error{
...@@ -489,6 +491,7 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -489,6 +491,7 @@ pub fn resolve(options: Options) ResolveError!Config {
489 .any_error_tracing = any_error_tracing,491 .any_error_tracing = any_error_tracing,
490 .any_sanitize_thread = options.any_sanitize_thread,492 .any_sanitize_thread = options.any_sanitize_thread,
491 .any_fuzz = options.any_fuzz,493 .any_fuzz = options.any_fuzz,
494 .san_cov_trace_pc_guard = options.san_cov_trace_pc_guard,
492 .root_error_tracing = root_error_tracing,495 .root_error_tracing = root_error_tracing,
493 .pie = pie,496 .pie = pie,
494 .lto = lto,497 .lto = lto,
src/clang_options_data.zig+10-3
...@@ -3825,7 +3825,14 @@ flagpd1("fsanitize-coverage-trace-div"),...@@ -3825,7 +3825,14 @@ flagpd1("fsanitize-coverage-trace-div"),
3825flagpd1("fsanitize-coverage-trace-gep"),3825flagpd1("fsanitize-coverage-trace-gep"),
3826flagpd1("fsanitize-coverage-trace-loads"),3826flagpd1("fsanitize-coverage-trace-loads"),
3827flagpd1("fsanitize-coverage-trace-pc"),3827flagpd1("fsanitize-coverage-trace-pc"),
3828flagpd1("fsanitize-coverage-trace-pc-guard"),3828.{
3829 .name = "fsanitize-coverage-trace-pc-guard",
3830 .syntax = .flag,
3831 .zig_equivalent = .san_cov_trace_pc_guard,
3832 .pd1 = true,
3833 .pd2 = false,
3834 .psl = false,
3835},
3829flagpd1("fsanitize-coverage-trace-stores"),3836flagpd1("fsanitize-coverage-trace-stores"),
3830flagpd1("fsanitize-hwaddress-experimental-aliasing"),3837flagpd1("fsanitize-hwaddress-experimental-aliasing"),
3831flagpd1("fsanitize-link-c++-runtime"),3838flagpd1("fsanitize-link-c++-runtime"),
...@@ -6012,7 +6019,7 @@ joinpd1("fmodules-ignore-macro="),...@@ -6012,7 +6019,7 @@ joinpd1("fmodules-ignore-macro="),
6012.{6019.{
6013 .name = "fno-sanitize-coverage=",6020 .name = "fno-sanitize-coverage=",
6014 .syntax = .comma_joined,6021 .syntax = .comma_joined,
6015 .zig_equivalent = .other,6022 .zig_equivalent = .no_san_cov,
6016 .pd1 = true,6023 .pd1 = true,
6017 .pd2 = false,6024 .pd2 = false,
6018 .psl = false,6025 .psl = false,
...@@ -6149,7 +6156,7 @@ joinpd1("fprofile-instr-use="),...@@ -6149,7 +6156,7 @@ joinpd1("fprofile-instr-use="),
6149.{6156.{
6150 .name = "fsanitize-coverage=",6157 .name = "fsanitize-coverage=",
6151 .syntax = .comma_joined,6158 .syntax = .comma_joined,
6152 .zig_equivalent = .other,6159 .zig_equivalent = .san_cov,
6153 .pd1 = true,6160 .pd1 = true,
6154 .pd2 = false,6161 .pd2 = false,
6155 .psl = false,6162 .psl = false,
src/codegen/llvm.zig+38-36
...@@ -1278,50 +1278,52 @@ pub const Object = struct {...@@ -1278,50 +1278,52 @@ pub const Object = struct {
1278 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.1278 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.
1279 // So we call the entire pipeline multiple times if this is requested.1279 // So we call the entire pipeline multiple times if this is requested.
1280 // var error_message: [*:0]const u8 = undefined;1280 // var error_message: [*:0]const u8 = undefined;
1281 var emit_bin_path = options.bin_path;1281 var lowered_options: llvm.TargetMachine.EmitOptions = .{
1282 var post_ir_path = options.post_ir_path;1282 .is_debug = options.is_debug,
1283 .is_small = options.is_small,
1284 .time_report = options.time_report,
1285 .tsan = options.sanitize_thread,
1286 .sancov = options.fuzz,
1287 .lto = options.lto,
1288 .asm_filename = null,
1289 .bin_filename = options.bin_path,
1290 .llvm_ir_filename = options.post_ir_path,
1291 .bitcode_filename = null,
1292 .coverage = .{
1293 .CoverageType = .Edge,
1294 .IndirectCalls = true,
1295 .TraceBB = false,
1296 .TraceCmp = true,
1297 .TraceDiv = false,
1298 .TraceGep = false,
1299 .Use8bitCounters = false,
1300 .TracePC = false,
1301 .TracePCGuard = comp.config.san_cov_trace_pc_guard,
1302 .Inline8bitCounters = true,
1303 .InlineBoolFlag = false,
1304 .PCTable = true,
1305 .NoPrune = false,
1306 .StackDepth = true,
1307 .TraceLoads = false,
1308 .TraceStores = false,
1309 .CollectControlFlow = false,
1310 },
1311 };
1283 if (options.asm_path != null and options.bin_path != null) {1312 if (options.asm_path != null and options.bin_path != null) {
1284 if (target_machine.emitToFile(1313 if (target_machine.emitToFile(module, &error_message, lowered_options)) {
1285 module,
1286 &error_message,
1287 options.is_debug,
1288 options.is_small,
1289 options.time_report,
1290 options.sanitize_thread,
1291 options.fuzz,
1292 options.lto,
1293 null,
1294 emit_bin_path,
1295 post_ir_path,
1296 null,
1297 )) {
1298 defer llvm.disposeMessage(error_message);1314 defer llvm.disposeMessage(error_message);
1299
1300 log.err("LLVM failed to emit bin={s} ir={s}: {s}", .{1315 log.err("LLVM failed to emit bin={s} ir={s}: {s}", .{
1301 emit_bin_msg, post_llvm_ir_msg, error_message,1316 emit_bin_msg, post_llvm_ir_msg, error_message,
1302 });1317 });
1303 return error.FailedToEmit;1318 return error.FailedToEmit;
1304 }1319 }
1305 emit_bin_path = null;1320 lowered_options.bin_filename = null;
1306 post_ir_path = null;1321 lowered_options.llvm_ir_filename = null;
1307 }1322 }
1308
1309 if (target_machine.emitToFile(
1310 module,
1311 &error_message,
1312 options.is_debug,
1313 options.is_small,
1314 options.time_report,
1315 options.sanitize_thread,
1316 options.fuzz,
1317 options.lto,
1318 options.asm_path,
1319 emit_bin_path,
1320 post_ir_path,
1321 null,
1322 )) {
1323 defer llvm.disposeMessage(error_message);
13241323
1324 lowered_options.asm_filename = options.asm_path;
1325 if (target_machine.emitToFile(module, &error_message, lowered_options)) {
1326 defer llvm.disposeMessage(error_message);
1325 log.err("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{1327 log.err("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{
1326 emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg,1328 emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg,
1327 error_message,1329 error_message,
src/codegen/llvm/bindings.zig+37-5
...@@ -84,11 +84,7 @@ pub const TargetMachine = opaque {...@@ -84,11 +84,7 @@ pub const TargetMachine = opaque {
84 pub const dispose = LLVMDisposeTargetMachine;84 pub const dispose = LLVMDisposeTargetMachine;
85 extern fn LLVMDisposeTargetMachine(T: *TargetMachine) void;85 extern fn LLVMDisposeTargetMachine(T: *TargetMachine) void;
8686
87 pub const emitToFile = ZigLLVMTargetMachineEmitToFile;87 pub const EmitOptions = extern struct {
88 extern fn ZigLLVMTargetMachineEmitToFile(
89 T: *TargetMachine,
90 M: *Module,
91 ErrorMessage: *[*:0]const u8,
92 is_debug: bool,88 is_debug: bool,
93 is_small: bool,89 is_small: bool,
94 time_report: bool,90 time_report: bool,
...@@ -99,6 +95,42 @@ pub const TargetMachine = opaque {...@@ -99,6 +95,42 @@ pub const TargetMachine = opaque {
99 bin_filename: ?[*:0]const u8,95 bin_filename: ?[*:0]const u8,
100 llvm_ir_filename: ?[*:0]const u8,96 llvm_ir_filename: ?[*:0]const u8,
101 bitcode_filename: ?[*:0]const u8,97 bitcode_filename: ?[*:0]const u8,
98 coverage: Coverage,
99
100 pub const Coverage = extern struct {
101 CoverageType: Coverage.Type,
102 IndirectCalls: bool,
103 TraceBB: bool,
104 TraceCmp: bool,
105 TraceDiv: bool,
106 TraceGep: bool,
107 Use8bitCounters: bool,
108 TracePC: bool,
109 TracePCGuard: bool,
110 Inline8bitCounters: bool,
111 InlineBoolFlag: bool,
112 PCTable: bool,
113 NoPrune: bool,
114 StackDepth: bool,
115 TraceLoads: bool,
116 TraceStores: bool,
117 CollectControlFlow: bool,
118
119 pub const Type = enum(c_uint) {
120 None = 0,
121 Function,
122 BB,
123 Edge,
124 };
125 };
126 };
127
128 pub const emitToFile = ZigLLVMTargetMachineEmitToFile;
129 extern fn ZigLLVMTargetMachineEmitToFile(
130 T: *TargetMachine,
131 M: *Module,
132 ErrorMessage: *[*:0]const u8,
133 options: EmitOptions,
102 ) bool;134 ) bool;
103135
104 pub const createTargetDataLayout = LLVMCreateTargetDataLayout;136 pub const createTargetDataLayout = LLVMCreateTargetDataLayout;
src/link/Elf.zig+6-4
...@@ -2673,12 +2673,14 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s...@@ -2673,12 +2673,14 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
2673 try argv.append(p);2673 try argv.append(p);
2674 }2674 }
26752675
2676 if (comp.config.any_sanitize_thread) {2676 if (comp.tsan_lib) |lib| {
2677 try argv.append(comp.tsan_lib.?.full_object_path);2677 assert(comp.config.any_sanitize_thread);
2678 try argv.append(lib.full_object_path);
2678 }2679 }
26792680
2680 if (comp.config.any_fuzz) {2681 if (comp.fuzzer_lib) |lib| {
2681 try argv.append(comp.fuzzer_lib.?.full_object_path);2682 assert(comp.config.any_fuzz);
2683 try argv.append(lib.full_object_path);
2682 }2684 }
26832685
2684 // libc2686 // libc
src/main.zig+26
...@@ -1454,6 +1454,10 @@ fn buildOutputType(...@@ -1454,6 +1454,10 @@ fn buildOutputType(
1454 create_module.opts.use_clang = true;1454 create_module.opts.use_clang = true;
1455 } else if (mem.eql(u8, arg, "-fno-clang")) {1455 } else if (mem.eql(u8, arg, "-fno-clang")) {
1456 create_module.opts.use_clang = false;1456 create_module.opts.use_clang = false;
1457 } else if (mem.eql(u8, arg, "-fsanitize-coverage-trace-pc-guard")) {
1458 create_module.opts.san_cov_trace_pc_guard = true;
1459 } else if (mem.eql(u8, arg, "-fno-sanitize-coverage-trace-pc-guard")) {
1460 create_module.opts.san_cov_trace_pc_guard = false;
1457 } else if (mem.eql(u8, arg, "-freference-trace")) {1461 } else if (mem.eql(u8, arg, "-freference-trace")) {
1458 reference_trace = 256;1462 reference_trace = 256;
1459 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {1463 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
...@@ -2025,6 +2029,25 @@ fn buildOutputType(...@@ -2025,6 +2029,25 @@ fn buildOutputType(
2025 }2029 }
2026 }2030 }
2027 },2031 },
2032 .san_cov_trace_pc_guard => create_module.opts.san_cov_trace_pc_guard = true,
2033 .san_cov => {
2034 var split_it = mem.splitScalar(u8, it.only_arg, ',');
2035 while (split_it.next()) |san_arg| {
2036 if (std.mem.eql(u8, san_arg, "trace-pc-guard")) {
2037 create_module.opts.san_cov_trace_pc_guard = true;
2038 }
2039 }
2040 try cc_argv.appendSlice(arena, it.other_args);
2041 },
2042 .no_san_cov => {
2043 var split_it = mem.splitScalar(u8, it.only_arg, ',');
2044 while (split_it.next()) |san_arg| {
2045 if (std.mem.eql(u8, san_arg, "trace-pc-guard")) {
2046 create_module.opts.san_cov_trace_pc_guard = false;
2047 }
2048 }
2049 try cc_argv.appendSlice(arena, it.other_args);
2050 },
2028 .optimize => {2051 .optimize => {
2029 // Alright, what release mode do they want?2052 // Alright, what release mode do they want?
2030 const level = if (it.only_arg.len >= 1 and it.only_arg[0] == 'O') it.only_arg[1..] else it.only_arg;2053 const level = if (it.only_arg.len >= 1 and it.only_arg[0] == 'O') it.only_arg[1..] else it.only_arg;
...@@ -5803,6 +5826,9 @@ pub const ClangArgIterator = struct {...@@ -5803,6 +5826,9 @@ pub const ClangArgIterator = struct {
5803 undefined,5826 undefined,
5804 force_load_objc,5827 force_load_objc,
5805 mingw_unicode_entry_point,5828 mingw_unicode_entry_point,
5829 san_cov_trace_pc_guard,
5830 san_cov,
5831 no_san_cov,
5806 };5832 };
58075833
5808 const Args = struct {5834 const Args = struct {
src/zig_llvm.cpp+46-49
...@@ -189,59 +189,56 @@ struct TimeTracerRAII {...@@ -189,59 +189,56 @@ struct TimeTracerRAII {
189};189};
190} // end anonymous namespace190} // end anonymous namespace
191191
192static SanitizerCoverageOptions getSanCovOptions(void) {192static SanitizerCoverageOptions getSanCovOptions(ZigLLVMCoverageOptions z) {
193 SanitizerCoverageOptions o;193 SanitizerCoverageOptions o;
194 o.CoverageType = SanitizerCoverageOptions::SCK_Edge;194 o.CoverageType = (SanitizerCoverageOptions::Type)z.CoverageType;
195 o.IndirectCalls = true;195 o.IndirectCalls = z.IndirectCalls;
196 o.TraceBB = false;196 o.TraceBB = z.TraceBB;
197 o.TraceCmp = true;197 o.TraceCmp = z.TraceCmp;
198 o.TraceDiv = false;198 o.TraceDiv = z.TraceDiv;
199 o.TraceGep = false;199 o.TraceGep = z.TraceGep;
200 o.Use8bitCounters = false;200 o.Use8bitCounters = z.Use8bitCounters;
201 o.TracePC = false;201 o.TracePC = z.TracePC;
202 o.TracePCGuard = false;202 o.TracePCGuard = z.TracePCGuard;
203 o.Inline8bitCounters = true;203 o.Inline8bitCounters = z.Inline8bitCounters;
204 o.InlineBoolFlag = false;204 o.InlineBoolFlag = z.InlineBoolFlag;
205 o.PCTable = true;205 o.PCTable = z.PCTable;
206 o.NoPrune = false;206 o.NoPrune = z.NoPrune;
207 o.StackDepth = true;207 o.StackDepth = z.StackDepth;
208 o.TraceLoads = false;208 o.TraceLoads = z.TraceLoads;
209 o.TraceStores = false;209 o.TraceStores = z.TraceStores;
210 o.CollectControlFlow = false;210 o.CollectControlFlow = z.CollectControlFlow;
211 return o;211 return o;
212}212}
213213
214bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,214ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
215 char **error_message, bool is_debug,215 char **error_message, struct ZigLLVMEmitOptions options)
216 bool is_small, bool time_report, bool tsan, bool sancov, bool lto,
217 const char *asm_filename, const char *bin_filename,
218 const char *llvm_ir_filename, const char *bitcode_filename)
219{216{
220 TimePassesIsEnabled = time_report;217 TimePassesIsEnabled = options.time_report;
221218
222 raw_fd_ostream *dest_asm_ptr = nullptr;219 raw_fd_ostream *dest_asm_ptr = nullptr;
223 raw_fd_ostream *dest_bin_ptr = nullptr;220 raw_fd_ostream *dest_bin_ptr = nullptr;
224 raw_fd_ostream *dest_bitcode_ptr = nullptr;221 raw_fd_ostream *dest_bitcode_ptr = nullptr;
225222
226 if (asm_filename) {223 if (options.asm_filename) {
227 std::error_code EC;224 std::error_code EC;
228 dest_asm_ptr = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::OF_None);225 dest_asm_ptr = new(std::nothrow) raw_fd_ostream(options.asm_filename, EC, sys::fs::OF_None);
229 if (EC) {226 if (EC) {
230 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());227 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
231 return true;228 return true;
232 }229 }
233 }230 }
234 if (bin_filename) {231 if (options.bin_filename) {
235 std::error_code EC;232 std::error_code EC;
236 dest_bin_ptr = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::OF_None);233 dest_bin_ptr = new(std::nothrow) raw_fd_ostream(options.bin_filename, EC, sys::fs::OF_None);
237 if (EC) {234 if (EC) {
238 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());235 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
239 return true;236 return true;
240 }237 }
241 }238 }
242 if (bitcode_filename) {239 if (options.bitcode_filename) {
243 std::error_code EC;240 std::error_code EC;
244 dest_bitcode_ptr = new(std::nothrow) raw_fd_ostream(bitcode_filename, EC, sys::fs::OF_None);241 dest_bitcode_ptr = new(std::nothrow) raw_fd_ostream(options.bitcode_filename, EC, sys::fs::OF_None);
245 if (EC) {242 if (EC) {
246 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());243 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
247 return true;244 return true;
...@@ -257,7 +254,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -257,7 +254,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
257 std::string ProcName = "zig-";254 std::string ProcName = "zig-";
258 ProcName += std::to_string(PID);255 ProcName += std::to_string(PID);
259 TimeTracerRAII TimeTracer(ProcName,256 TimeTracerRAII TimeTracer(ProcName,
260 bin_filename? bin_filename : asm_filename);257 options.bin_filename? options.bin_filename : options.asm_filename);
261258
262 TargetMachine &target_machine = *reinterpret_cast<TargetMachine*>(targ_machine_ref);259 TargetMachine &target_machine = *reinterpret_cast<TargetMachine*>(targ_machine_ref);
263 target_machine.setO0WantsFastISel(true);260 target_machine.setO0WantsFastISel(true);
...@@ -266,11 +263,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -266,11 +263,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
266263
267 // Pipeline configurations264 // Pipeline configurations
268 PipelineTuningOptions pipeline_opts;265 PipelineTuningOptions pipeline_opts;
269 pipeline_opts.LoopUnrolling = !is_debug;266 pipeline_opts.LoopUnrolling = !options.is_debug;
270 pipeline_opts.SLPVectorization = !is_debug;267 pipeline_opts.SLPVectorization = !options.is_debug;
271 pipeline_opts.LoopVectorization = !is_debug;268 pipeline_opts.LoopVectorization = !options.is_debug;
272 pipeline_opts.LoopInterleaving = !is_debug;269 pipeline_opts.LoopInterleaving = !options.is_debug;
273 pipeline_opts.MergeFunctions = !is_debug;270 pipeline_opts.MergeFunctions = !options.is_debug;
274271
275 // Instrumentations272 // Instrumentations
276 PassInstrumentationCallbacks instr_callbacks;273 PassInstrumentationCallbacks instr_callbacks;
...@@ -308,19 +305,19 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -308,19 +305,19 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
308 module_pm.addPass(VerifierPass());305 module_pm.addPass(VerifierPass());
309 }306 }
310307
311 if (!is_debug) {308 if (!options.is_debug) {
312 module_pm.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass()));309 module_pm.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass()));
313 }310 }
314 });311 });
315312
316 pass_builder.registerOptimizerEarlyEPCallback([&](ModulePassManager &module_pm, OptimizationLevel OL) {313 pass_builder.registerOptimizerEarlyEPCallback([&](ModulePassManager &module_pm, OptimizationLevel OL) {
317 // Code coverage instrumentation.314 // Code coverage instrumentation.
318 if (sancov) {315 if (options.sancov) {
319 module_pm.addPass(SanitizerCoveragePass(getSanCovOptions()));316 module_pm.addPass(SanitizerCoveragePass(getSanCovOptions(options.coverage)));
320 }317 }
321318
322 // Thread sanitizer319 // Thread sanitizer
323 if (tsan) {320 if (options.tsan) {
324 module_pm.addPass(ModuleThreadSanitizerPass());321 module_pm.addPass(ModuleThreadSanitizerPass());
325 module_pm.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));322 module_pm.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
326 }323 }
...@@ -336,17 +333,17 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -336,17 +333,17 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
336 ModulePassManager module_pm;333 ModulePassManager module_pm;
337 OptimizationLevel opt_level;334 OptimizationLevel opt_level;
338 // Setting up the optimization level335 // Setting up the optimization level
339 if (is_debug)336 if (options.is_debug)
340 opt_level = OptimizationLevel::O0;337 opt_level = OptimizationLevel::O0;
341 else if (is_small)338 else if (options.is_small)
342 opt_level = OptimizationLevel::Oz;339 opt_level = OptimizationLevel::Oz;
343 else340 else
344 opt_level = OptimizationLevel::O3;341 opt_level = OptimizationLevel::O3;
345342
346 // Initialize the PassManager343 // Initialize the PassManager
347 if (opt_level == OptimizationLevel::O0) {344 if (opt_level == OptimizationLevel::O0) {
348 module_pm = pass_builder.buildO0DefaultPipeline(opt_level, lto);345 module_pm = pass_builder.buildO0DefaultPipeline(opt_level, options.lto);
349 } else if (lto) {346 } else if (options.lto) {
350 module_pm = pass_builder.buildLTOPreLinkDefaultPipeline(opt_level);347 module_pm = pass_builder.buildLTOPreLinkDefaultPipeline(opt_level);
351 } else {348 } else {
352 module_pm = pass_builder.buildPerModuleDefaultPipeline(opt_level);349 module_pm = pass_builder.buildPerModuleDefaultPipeline(opt_level);
...@@ -357,7 +354,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -357,7 +354,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
357 codegen_pm.add(354 codegen_pm.add(
358 createTargetTransformInfoWrapperPass(target_machine.getTargetIRAnalysis()));355 createTargetTransformInfoWrapperPass(target_machine.getTargetIRAnalysis()));
359356
360 if (dest_bin && !lto) {357 if (dest_bin && !options.lto) {
361 if (target_machine.addPassesToEmitFile(codegen_pm, *dest_bin, nullptr, CodeGenFileType::ObjectFile)) {358 if (target_machine.addPassesToEmitFile(codegen_pm, *dest_bin, nullptr, CodeGenFileType::ObjectFile)) {
362 *error_message = strdup("TargetMachine can't emit an object file");359 *error_message = strdup("TargetMachine can't emit an object file");
363 return true;360 return true;
...@@ -376,20 +373,20 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -376,20 +373,20 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
376 // Code generation phase373 // Code generation phase
377 codegen_pm.run(llvm_module);374 codegen_pm.run(llvm_module);
378375
379 if (llvm_ir_filename) {376 if (options.llvm_ir_filename) {
380 if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) {377 if (LLVMPrintModuleToFile(module_ref, options.llvm_ir_filename, error_message)) {
381 return true;378 return true;
382 }379 }
383 }380 }
384381
385 if (dest_bin && lto) {382 if (dest_bin && options.lto) {
386 WriteBitcodeToFile(llvm_module, *dest_bin);383 WriteBitcodeToFile(llvm_module, *dest_bin);
387 }384 }
388 if (dest_bitcode) {385 if (dest_bitcode) {
389 WriteBitcodeToFile(llvm_module, *dest_bitcode);386 WriteBitcodeToFile(llvm_module, *dest_bitcode);
390 }387 }
391388
392 if (time_report) {389 if (options.time_report) {
393 TimerGroup::printAll(errs());390 TimerGroup::printAll(errs());
394 }391 }
395392
src/zig_llvm.h+43-5
...@@ -24,12 +24,50 @@...@@ -24,12 +24,50 @@
24// ATTENTION: If you modify this file, be sure to update the corresponding24// ATTENTION: If you modify this file, be sure to update the corresponding
25// extern function declarations in the self-hosted compiler.25// extern function declarations in the self-hosted compiler.
2626
27ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
28 char **error_message, bool is_debug,
29 bool is_small, bool time_report, bool tsan, bool sancov, bool lto,
30 const char *asm_filename, const char *bin_filename,
31 const char *llvm_ir_filename, const char *bitcode_filename);
3227
28enum ZigLLVMCoverageType {
29 ZigLLVMCoverageType_None = 0,
30 ZigLLVMCoverageType_Function,
31 ZigLLVMCoverageType_BB,
32 ZigLLVMCoverageType_Edge
33};
34
35struct ZigLLVMCoverageOptions {
36 ZigLLVMCoverageType CoverageType;
37 bool IndirectCalls;
38 bool TraceBB;
39 bool TraceCmp;
40 bool TraceDiv;
41 bool TraceGep;
42 bool Use8bitCounters;
43 bool TracePC;
44 bool TracePCGuard;
45 bool Inline8bitCounters;
46 bool InlineBoolFlag;
47 bool PCTable;
48 bool NoPrune;
49 bool StackDepth;
50 bool TraceLoads;
51 bool TraceStores;
52 bool CollectControlFlow;
53};
54
55struct ZigLLVMEmitOptions {
56 bool is_debug;
57 bool is_small;
58 bool time_report;
59 bool tsan;
60 bool sancov;
61 bool lto;
62 const char *asm_filename;
63 const char *bin_filename;
64 const char *llvm_ir_filename;
65 const char *bitcode_filename;
66 ZigLLVMCoverageOptions coverage;
67};
68
69ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
70 char **error_message, struct ZigLLVMEmitOptions options);
3371
34enum ZigLLVMABIType {72enum ZigLLVMABIType {
35 ZigLLVMABITypeDefault, // Target-specific (either soft or hard depending on triple, etc).73 ZigLLVMABITypeDefault, // Target-specific (either soft or hard depending on triple, etc).
tools/update_clang_options.zig+12
...@@ -536,6 +536,18 @@ const known_options = [_]KnownOpt{...@@ -536,6 +536,18 @@ const known_options = [_]KnownOpt{
536 .name = "municode",536 .name = "municode",
537 .ident = "mingw_unicode_entry_point",537 .ident = "mingw_unicode_entry_point",
538 },538 },
539 .{
540 .name = "fsanitize-coverage-trace-pc-guard",
541 .ident = "san_cov_trace_pc_guard",
542 },
543 .{
544 .name = "fsanitize-coverage",
545 .ident = "san_cov",
546 },
547 .{
548 .name = "fno-sanitize-coverage",
549 .ident = "no_san_cov",
550 },
539};551};
540552
541const blacklisted_options = [_][]const u8{};553const blacklisted_options = [_][]const u8{};