| author | |
| committer | |
| log | 75cf7fca900766713597d21d141292b3725aac50 |
| tree | 7c95e5dd446d8864053f0f366695c75e6af9a2b0 |
| parent | 1e74904aa27da423bcfe804a9b06fe8c0a0620ba |
| parent | 26d2a7960e9199989d9387e0af29497581422f93 |
| signature |
add "trace pc guard" as optional additional coverage instrumentation11 files changed, 235 insertions(+), 102 deletions(-)
lib/std/Build/Step/Compile.zig+9| ... | ... | @@ -217,6 +217,14 @@ no_builtin: bool = false, |
| 217 | 217 | /// Managed by the build runner, not user build script. |
| 218 | 218 | zig_process: ?*Step.ZigProcess, |
| 219 | 219 | |
| 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`. | |
| 226 | sanitize_coverage_trace_pc_guard: ?bool = null, | |
| 227 | ||
| 220 | 228 | pub const ExpectedCompileErrors = union(enum) { |
| 221 | 229 | contains: []const u8, |
| 222 | 230 | exact: []const []const u8, |
| ... | ... | @@ -1656,6 +1664,7 @@ fn getZigArgs(compile: *Compile) ![][]const u8 { |
| 1656 | 1664 | |
| 1657 | 1665 | try addFlag(&zig_args, "PIE", compile.pie); |
| 1658 | 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); | |
| 1659 | 1668 | |
| 1660 | 1669 | if (compile.subsystem) |subsystem| { |
| 1661 | 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 | 1412 | cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs); |
| 1413 | 1413 | cache.hash.addBytes(options.root_name); |
| 1414 | 1414 | cache.hash.add(options.config.wasi_exec_model); |
| 1415 | cache.hash.add(options.config.san_cov_trace_pc_guard); | |
| 1415 | 1416 | // TODO audit this and make sure everything is in it |
| 1416 | 1417 | |
| 1417 | 1418 | const main_mod = options.main_mod orelse options.root_mod; |
| ... | ... | @@ -5652,6 +5653,10 @@ pub fn addCCArgs( |
| 5652 | 5653 | // function was called. |
| 5653 | 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 | } |
| 5657 | 5662 |
src/Compilation/Config.zig+3| ... | ... | @@ -60,6 +60,7 @@ root_strip: bool, |
| 60 | 60 | root_error_tracing: bool, |
| 61 | 61 | dll_export_fns: bool, |
| 62 | 62 | rdynamic: bool, |
| 63 | san_cov_trace_pc_guard: bool, | |
| 63 | 64 | |
| 64 | 65 | pub const CFrontend = enum { clang, aro }; |
| 65 | 66 | |
| ... | ... | @@ -108,6 +109,7 @@ pub const Options = struct { |
| 108 | 109 | debug_format: ?DebugFormat = null, |
| 109 | 110 | dll_export_fns: ?bool = null, |
| 110 | 111 | rdynamic: ?bool = null, |
| 112 | san_cov_trace_pc_guard: bool = false, | |
| 111 | 113 | }; |
| 112 | 114 | |
| 113 | 115 | pub const ResolveError = error{ |
| ... | ... | @@ -489,6 +491,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 489 | 491 | .any_error_tracing = any_error_tracing, |
| 490 | 492 | .any_sanitize_thread = options.any_sanitize_thread, |
| 491 | 493 | .any_fuzz = options.any_fuzz, |
| 494 | .san_cov_trace_pc_guard = options.san_cov_trace_pc_guard, | |
| 492 | 495 | .root_error_tracing = root_error_tracing, |
| 493 | 496 | .pie = pie, |
| 494 | 497 | .lto = lto, |
src/clang_options_data.zig+10-3| ... | ... | @@ -3825,7 +3825,14 @@ flagpd1("fsanitize-coverage-trace-div"), |
| 3825 | 3825 | flagpd1("fsanitize-coverage-trace-gep"), |
| 3826 | 3826 | flagpd1("fsanitize-coverage-trace-loads"), |
| 3827 | 3827 | flagpd1("fsanitize-coverage-trace-pc"), |
| 3828 | flagpd1("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 | }, | |
| 3829 | 3836 | flagpd1("fsanitize-coverage-trace-stores"), |
| 3830 | 3837 | flagpd1("fsanitize-hwaddress-experimental-aliasing"), |
| 3831 | 3838 | flagpd1("fsanitize-link-c++-runtime"), |
| ... | ... | @@ -6012,7 +6019,7 @@ joinpd1("fmodules-ignore-macro="), |
| 6012 | 6019 | .{ |
| 6013 | 6020 | .name = "fno-sanitize-coverage=", |
| 6014 | 6021 | .syntax = .comma_joined, |
| 6015 | .zig_equivalent = .other, | |
| 6022 | .zig_equivalent = .no_san_cov, | |
| 6016 | 6023 | .pd1 = true, |
| 6017 | 6024 | .pd2 = false, |
| 6018 | 6025 | .psl = false, |
| ... | ... | @@ -6149,7 +6156,7 @@ joinpd1("fprofile-instr-use="), |
| 6149 | 6156 | .{ |
| 6150 | 6157 | .name = "fsanitize-coverage=", |
| 6151 | 6158 | .syntax = .comma_joined, |
| 6152 | .zig_equivalent = .other, | |
| 6159 | .zig_equivalent = .san_cov, | |
| 6153 | 6160 | .pd1 = true, |
| 6154 | 6161 | .pd2 = false, |
| 6155 | 6162 | .psl = false, |
src/codegen/llvm.zig+38-36| ... | ... | @@ -1278,50 +1278,52 @@ pub const Object = struct { |
| 1278 | 1278 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. |
| 1279 | 1279 | // So we call the entire pipeline multiple times if this is requested. |
| 1280 | 1280 | // var error_message: [*:0]const u8 = undefined; |
| 1281 | var emit_bin_path = options.bin_path; | |
| 1282 | var post_ir_path = options.post_ir_path; | |
| 1281 | var lowered_options: llvm.TargetMachine.EmitOptions = .{ | |
| 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 | 1312 | if (options.asm_path != null and options.bin_path != null) { |
| 1284 | if (target_machine.emitToFile( | |
| 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 | )) { | |
| 1313 | if (target_machine.emitToFile(module, &error_message, lowered_options)) { | |
| 1298 | 1314 | defer llvm.disposeMessage(error_message); |
| 1299 | ||
| 1300 | 1315 | log.err("LLVM failed to emit bin={s} ir={s}: {s}", .{ |
| 1301 | 1316 | emit_bin_msg, post_llvm_ir_msg, error_message, |
| 1302 | 1317 | }); |
| 1303 | 1318 | return error.FailedToEmit; |
| 1304 | 1319 | } |
| 1305 | emit_bin_path = null; | |
| 1306 | post_ir_path = null; | |
| 1307 | } | |
| 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); | |
| 1320 | lowered_options.bin_filename = null; | |
| 1321 | lowered_options.llvm_ir_filename = null; | |
| 1322 | } | |
| 1324 | 1323 | |
| 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 | 1327 | log.err("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{ |
| 1326 | 1328 | emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg, |
| 1327 | 1329 | error_message, |
src/codegen/llvm/bindings.zig+37-5| ... | ... | @@ -84,11 +84,7 @@ pub const TargetMachine = opaque { |
| 84 | 84 | pub const dispose = LLVMDisposeTargetMachine; |
| 85 | 85 | extern fn LLVMDisposeTargetMachine(T: *TargetMachine) void; |
| 86 | 86 | |
| 87 | pub const emitToFile = ZigLLVMTargetMachineEmitToFile; | |
| 88 | extern fn ZigLLVMTargetMachineEmitToFile( | |
| 89 | T: *TargetMachine, | |
| 90 | M: *Module, | |
| 91 | ErrorMessage: *[*:0]const u8, | |
| 87 | pub const EmitOptions = extern struct { | |
| 92 | 88 | is_debug: bool, |
| 93 | 89 | is_small: bool, |
| 94 | 90 | time_report: bool, |
| ... | ... | @@ -99,6 +95,42 @@ pub const TargetMachine = opaque { |
| 99 | 95 | bin_filename: ?[*:0]const u8, |
| 100 | 96 | llvm_ir_filename: ?[*:0]const u8, |
| 101 | 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 | 134 | ) bool; |
| 103 | 135 | |
| 104 | 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 | 2673 | try argv.append(p); |
| 2674 | 2674 | } |
| 2675 | 2675 | |
| 2676 | if (comp.config.any_sanitize_thread) { | |
| 2677 | try argv.append(comp.tsan_lib.?.full_object_path); | |
| 2676 | if (comp.tsan_lib) |lib| { | |
| 2677 | assert(comp.config.any_sanitize_thread); | |
| 2678 | try argv.append(lib.full_object_path); | |
| 2678 | 2679 | } |
| 2679 | 2680 | |
| 2680 | if (comp.config.any_fuzz) { | |
| 2681 | try argv.append(comp.fuzzer_lib.?.full_object_path); | |
| 2681 | if (comp.fuzzer_lib) |lib| { | |
| 2682 | assert(comp.config.any_fuzz); | |
| 2683 | try argv.append(lib.full_object_path); | |
| 2682 | 2684 | } |
| 2683 | 2685 | |
| 2684 | 2686 | // libc |
src/main.zig+26| ... | ... | @@ -1454,6 +1454,10 @@ fn buildOutputType( |
| 1454 | 1454 | create_module.opts.use_clang = true; |
| 1455 | 1455 | } else if (mem.eql(u8, arg, "-fno-clang")) { |
| 1456 | 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 | 1461 | } else if (mem.eql(u8, arg, "-freference-trace")) { |
| 1458 | 1462 | reference_trace = 256; |
| 1459 | 1463 | } else if (mem.startsWith(u8, arg, "-freference-trace=")) { |
| ... | ... | @@ -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 | 2051 | .optimize => { |
| 2029 | 2052 | // Alright, what release mode do they want? |
| 2030 | 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 | 5826 | undefined, |
| 5804 | 5827 | force_load_objc, |
| 5805 | 5828 | mingw_unicode_entry_point, |
| 5829 | san_cov_trace_pc_guard, | |
| 5830 | san_cov, | |
| 5831 | no_san_cov, | |
| 5806 | 5832 | }; |
| 5807 | 5833 | |
| 5808 | 5834 | const Args = struct { |
src/zig_llvm.cpp+46-49| ... | ... | @@ -189,59 +189,56 @@ struct TimeTracerRAII { |
| 189 | 189 | }; |
| 190 | 190 | } // end anonymous namespace |
| 191 | 191 | |
| 192 | static SanitizerCoverageOptions getSanCovOptions(void) { | |
| 192 | static SanitizerCoverageOptions getSanCovOptions(ZigLLVMCoverageOptions z) { | |
| 193 | 193 | SanitizerCoverageOptions o; |
| 194 | o.CoverageType = SanitizerCoverageOptions::SCK_Edge; | |
| 195 | o.IndirectCalls = true; | |
| 196 | o.TraceBB = false; | |
| 197 | o.TraceCmp = true; | |
| 198 | o.TraceDiv = false; | |
| 199 | o.TraceGep = false; | |
| 200 | o.Use8bitCounters = false; | |
| 201 | o.TracePC = false; | |
| 202 | o.TracePCGuard = false; | |
| 203 | o.Inline8bitCounters = true; | |
| 204 | o.InlineBoolFlag = false; | |
| 205 | o.PCTable = true; | |
| 206 | o.NoPrune = false; | |
| 207 | o.StackDepth = true; | |
| 208 | o.TraceLoads = false; | |
| 209 | o.TraceStores = false; | |
| 210 | o.CollectControlFlow = false; | |
| 194 | o.CoverageType = (SanitizerCoverageOptions::Type)z.CoverageType; | |
| 195 | o.IndirectCalls = z.IndirectCalls; | |
| 196 | o.TraceBB = z.TraceBB; | |
| 197 | o.TraceCmp = z.TraceCmp; | |
| 198 | o.TraceDiv = z.TraceDiv; | |
| 199 | o.TraceGep = z.TraceGep; | |
| 200 | o.Use8bitCounters = z.Use8bitCounters; | |
| 201 | o.TracePC = z.TracePC; | |
| 202 | o.TracePCGuard = z.TracePCGuard; | |
| 203 | o.Inline8bitCounters = z.Inline8bitCounters; | |
| 204 | o.InlineBoolFlag = z.InlineBoolFlag; | |
| 205 | o.PCTable = z.PCTable; | |
| 206 | o.NoPrune = z.NoPrune; | |
| 207 | o.StackDepth = z.StackDepth; | |
| 208 | o.TraceLoads = z.TraceLoads; | |
| 209 | o.TraceStores = z.TraceStores; | |
| 210 | o.CollectControlFlow = z.CollectControlFlow; | |
| 211 | 211 | return o; |
| 212 | 212 | } |
| 213 | 213 | |
| 214 | bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, | |
| 215 | char **error_message, bool is_debug, | |
| 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) | |
| 214 | ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, | |
| 215 | char **error_message, struct ZigLLVMEmitOptions options) | |
| 219 | 216 | { |
| 220 | TimePassesIsEnabled = time_report; | |
| 217 | TimePassesIsEnabled = options.time_report; | |
| 221 | 218 | |
| 222 | 219 | raw_fd_ostream *dest_asm_ptr = nullptr; |
| 223 | 220 | raw_fd_ostream *dest_bin_ptr = nullptr; |
| 224 | 221 | raw_fd_ostream *dest_bitcode_ptr = nullptr; |
| 225 | 222 | |
| 226 | if (asm_filename) { | |
| 223 | if (options.asm_filename) { | |
| 227 | 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 | 226 | if (EC) { |
| 230 | 227 | *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); |
| 231 | 228 | return true; |
| 232 | 229 | } |
| 233 | 230 | } |
| 234 | if (bin_filename) { | |
| 231 | if (options.bin_filename) { | |
| 235 | 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 | 234 | if (EC) { |
| 238 | 235 | *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); |
| 239 | 236 | return true; |
| 240 | 237 | } |
| 241 | 238 | } |
| 242 | if (bitcode_filename) { | |
| 239 | if (options.bitcode_filename) { | |
| 243 | 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 | 242 | if (EC) { |
| 246 | 243 | *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); |
| 247 | 244 | return true; |
| ... | ... | @@ -257,7 +254,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 257 | 254 | std::string ProcName = "zig-"; |
| 258 | 255 | ProcName += std::to_string(PID); |
| 259 | 256 | TimeTracerRAII TimeTracer(ProcName, |
| 260 | bin_filename? bin_filename : asm_filename); | |
| 257 | options.bin_filename? options.bin_filename : options.asm_filename); | |
| 261 | 258 | |
| 262 | 259 | TargetMachine &target_machine = *reinterpret_cast<TargetMachine*>(targ_machine_ref); |
| 263 | 260 | target_machine.setO0WantsFastISel(true); |
| ... | ... | @@ -266,11 +263,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 266 | 263 | |
| 267 | 264 | // Pipeline configurations |
| 268 | 265 | PipelineTuningOptions pipeline_opts; |
| 269 | pipeline_opts.LoopUnrolling = !is_debug; | |
| 270 | pipeline_opts.SLPVectorization = !is_debug; | |
| 271 | pipeline_opts.LoopVectorization = !is_debug; | |
| 272 | pipeline_opts.LoopInterleaving = !is_debug; | |
| 273 | pipeline_opts.MergeFunctions = !is_debug; | |
| 266 | pipeline_opts.LoopUnrolling = !options.is_debug; | |
| 267 | pipeline_opts.SLPVectorization = !options.is_debug; | |
| 268 | pipeline_opts.LoopVectorization = !options.is_debug; | |
| 269 | pipeline_opts.LoopInterleaving = !options.is_debug; | |
| 270 | pipeline_opts.MergeFunctions = !options.is_debug; | |
| 274 | 271 | |
| 275 | 272 | // Instrumentations |
| 276 | 273 | PassInstrumentationCallbacks instr_callbacks; |
| ... | ... | @@ -308,19 +305,19 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 308 | 305 | module_pm.addPass(VerifierPass()); |
| 309 | 306 | } |
| 310 | 307 | |
| 311 | if (!is_debug) { | |
| 308 | if (!options.is_debug) { | |
| 312 | 309 | module_pm.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); |
| 313 | 310 | } |
| 314 | 311 | }); |
| 315 | 312 | |
| 316 | 313 | pass_builder.registerOptimizerEarlyEPCallback([&](ModulePassManager &module_pm, OptimizationLevel OL) { |
| 317 | 314 | // Code coverage instrumentation. |
| 318 | if (sancov) { | |
| 319 | module_pm.addPass(SanitizerCoveragePass(getSanCovOptions())); | |
| 315 | if (options.sancov) { | |
| 316 | module_pm.addPass(SanitizerCoveragePass(getSanCovOptions(options.coverage))); | |
| 320 | 317 | } |
| 321 | 318 | |
| 322 | 319 | // Thread sanitizer |
| 323 | if (tsan) { | |
| 320 | if (options.tsan) { | |
| 324 | 321 | module_pm.addPass(ModuleThreadSanitizerPass()); |
| 325 | 322 | module_pm.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); |
| 326 | 323 | } |
| ... | ... | @@ -336,17 +333,17 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 336 | 333 | ModulePassManager module_pm; |
| 337 | 334 | OptimizationLevel opt_level; |
| 338 | 335 | // Setting up the optimization level |
| 339 | if (is_debug) | |
| 336 | if (options.is_debug) | |
| 340 | 337 | opt_level = OptimizationLevel::O0; |
| 341 | else if (is_small) | |
| 338 | else if (options.is_small) | |
| 342 | 339 | opt_level = OptimizationLevel::Oz; |
| 343 | 340 | else |
| 344 | 341 | opt_level = OptimizationLevel::O3; |
| 345 | 342 | |
| 346 | 343 | // Initialize the PassManager |
| 347 | 344 | if (opt_level == OptimizationLevel::O0) { |
| 348 | module_pm = pass_builder.buildO0DefaultPipeline(opt_level, lto); | |
| 349 | } else if (lto) { | |
| 345 | module_pm = pass_builder.buildO0DefaultPipeline(opt_level, options.lto); | |
| 346 | } else if (options.lto) { | |
| 350 | 347 | module_pm = pass_builder.buildLTOPreLinkDefaultPipeline(opt_level); |
| 351 | 348 | } else { |
| 352 | 349 | module_pm = pass_builder.buildPerModuleDefaultPipeline(opt_level); |
| ... | ... | @@ -357,7 +354,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 357 | 354 | codegen_pm.add( |
| 358 | 355 | createTargetTransformInfoWrapperPass(target_machine.getTargetIRAnalysis())); |
| 359 | 356 | |
| 360 | if (dest_bin && !lto) { | |
| 357 | if (dest_bin && !options.lto) { | |
| 361 | 358 | if (target_machine.addPassesToEmitFile(codegen_pm, *dest_bin, nullptr, CodeGenFileType::ObjectFile)) { |
| 362 | 359 | *error_message = strdup("TargetMachine can't emit an object file"); |
| 363 | 360 | return true; |
| ... | ... | @@ -376,20 +373,20 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 376 | 373 | // Code generation phase |
| 377 | 374 | codegen_pm.run(llvm_module); |
| 378 | 375 | |
| 379 | if (llvm_ir_filename) { | |
| 380 | if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) { | |
| 376 | if (options.llvm_ir_filename) { | |
| 377 | if (LLVMPrintModuleToFile(module_ref, options.llvm_ir_filename, error_message)) { | |
| 381 | 378 | return true; |
| 382 | 379 | } |
| 383 | 380 | } |
| 384 | 381 | |
| 385 | if (dest_bin && lto) { | |
| 382 | if (dest_bin && options.lto) { | |
| 386 | 383 | WriteBitcodeToFile(llvm_module, *dest_bin); |
| 387 | 384 | } |
| 388 | 385 | if (dest_bitcode) { |
| 389 | 386 | WriteBitcodeToFile(llvm_module, *dest_bitcode); |
| 390 | 387 | } |
| 391 | 388 | |
| 392 | if (time_report) { | |
| 389 | if (options.time_report) { | |
| 393 | 390 | TimerGroup::printAll(errs()); |
| 394 | 391 | } |
| 395 | 392 |
src/zig_llvm.h+43-5| ... | ... | @@ -24,12 +24,50 @@ |
| 24 | 24 | // ATTENTION: If you modify this file, be sure to update the corresponding |
| 25 | 25 | // extern function declarations in the self-hosted compiler. |
| 26 | 26 | |
| 27 | ZIG_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); | |
| 32 | 27 | |
| 28 | enum ZigLLVMCoverageType { | |
| 29 | ZigLLVMCoverageType_None = 0, | |
| 30 | ZigLLVMCoverageType_Function, | |
| 31 | ZigLLVMCoverageType_BB, | |
| 32 | ZigLLVMCoverageType_Edge | |
| 33 | }; | |
| 34 | ||
| 35 | struct 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 | ||
| 55 | struct 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 | ||
| 69 | ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, | |
| 70 | char **error_message, struct ZigLLVMEmitOptions options); | |
| 33 | 71 | |
| 34 | 72 | enum ZigLLVMABIType { |
| 35 | 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 | 536 | .name = "municode", |
| 537 | 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 | }; |
| 540 | 552 | |
| 541 | 553 | const blacklisted_options = [_][]const u8{}; |