From 9e11c4f60ea56af50bed7bb27984307762d5f167 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 28 Aug 2024 15:18:42 -0700 Subject: [PATCH] LLVM: put sancov globals into llvm.compiler.used This matches what LLVM's sancov pass does and is required so that optimization passes do not delete the instrumentation. However, this is currently triggering an error: "members of llvm.compiler.used must be named" so the next commit will add names to those globals. --- src/codegen/llvm.zig | 72 +++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index d59fdd42a3..b78e2addef 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -822,6 +822,9 @@ pub const Object = struct { /// This is denormalized data. struct_field_map: std.AutoHashMapUnmanaged(ZigStructField, c_uint), + /// Values for `@llvm.compiler.used`. + compiler_used: std.ArrayListUnmanaged(Builder.Constant), + const ZigStructField = struct { struct_ty: InternPool.Index, field_index: u32, @@ -975,6 +978,7 @@ pub const Object = struct { .error_name_table = .none, .null_opt_usize = .no_init, .struct_field_map = .{}, + .compiler_used = .{}, }; return obj; } @@ -1097,44 +1101,57 @@ pub const Object = struct { lto: bool, }; - pub fn emit(self: *Object, options: EmitOptions) !void { - const zcu = self.pt.zcu; + pub fn emit(o: *Object, options: EmitOptions) !void { + const zcu = o.pt.zcu; const comp = zcu.comp; { - try self.genErrorNameTable(); - try self.genCmpLtErrorsLenFunction(); - try self.genModuleLevelAssembly(); + try o.genErrorNameTable(); + try o.genCmpLtErrorsLenFunction(); + try o.genModuleLevelAssembly(); - if (!self.builder.strip) { + if (o.compiler_used.items.len > 0) { + const array_llvm_ty = try o.builder.arrayType(o.compiler_used.items.len, .ptr); + const init_val = try o.builder.arrayConst(array_llvm_ty, o.compiler_used.items); + const compiler_used_variable = try o.builder.addVariable( + try o.builder.strtabString("llvm.compiler.used"), + array_llvm_ty, + .default, + ); + compiler_used_variable.setLinkage(.appending, &o.builder); + compiler_used_variable.setSection(try o.builder.string("llvm.metadata"), &o.builder); + try compiler_used_variable.setInitializer(init_val, &o.builder); + } + + if (!o.builder.strip) { { var i: usize = 0; - while (i < self.debug_unresolved_namespace_scopes.count()) : (i += 1) { - const namespace_index = self.debug_unresolved_namespace_scopes.keys()[i]; - const fwd_ref = self.debug_unresolved_namespace_scopes.values()[i]; + while (i < o.debug_unresolved_namespace_scopes.count()) : (i += 1) { + const namespace_index = o.debug_unresolved_namespace_scopes.keys()[i]; + const fwd_ref = o.debug_unresolved_namespace_scopes.values()[i]; const namespace = zcu.namespacePtr(namespace_index); - const debug_type = try self.lowerDebugType(Type.fromInterned(namespace.owner_type)); + const debug_type = try o.lowerDebugType(Type.fromInterned(namespace.owner_type)); - self.builder.debugForwardReferenceSetType(fwd_ref, debug_type); + o.builder.debugForwardReferenceSetType(fwd_ref, debug_type); } } - self.builder.debugForwardReferenceSetType( - self.debug_enums_fwd_ref, - try self.builder.metadataTuple(self.debug_enums.items), + o.builder.debugForwardReferenceSetType( + o.debug_enums_fwd_ref, + try o.builder.metadataTuple(o.debug_enums.items), ); - self.builder.debugForwardReferenceSetType( - self.debug_globals_fwd_ref, - try self.builder.metadataTuple(self.debug_globals.items), + o.builder.debugForwardReferenceSetType( + o.debug_globals_fwd_ref, + try o.builder.metadataTuple(o.debug_globals.items), ); } } const target_triple_sentinel = - try self.gpa.dupeZ(u8, self.builder.target_triple.slice(&self.builder).?); - defer self.gpa.free(target_triple_sentinel); + try o.gpa.dupeZ(u8, o.builder.target_triple.slice(&o.builder).?); + defer o.gpa.free(target_triple_sentinel); const emit_asm_msg = options.asm_path orelse "(none)"; const emit_bin_msg = options.bin_path orelse "(none)"; @@ -1147,15 +1164,15 @@ pub const Object = struct { const context, const module = emit: { if (options.pre_ir_path) |path| { if (std.mem.eql(u8, path, "-")) { - self.builder.dump(); + o.builder.dump(); } else { - _ = try self.builder.printToFile(path); + _ = try o.builder.printToFile(path); } } - const bitcode = try self.builder.toBitcode(self.gpa); - defer self.gpa.free(bitcode); - self.builder.clearAndFree(); + const bitcode = try o.builder.toBitcode(o.gpa); + defer o.gpa.free(bitcode); + o.builder.clearAndFree(); if (options.pre_bc_path) |path| { var file = try std.fs.cwd().createFile(path, .{}); @@ -1707,7 +1724,7 @@ pub const Object = struct { fg.genBody(air.getMainBody(), .poi) catch |err| switch (err) { error.CodegenFail => { - try zcu.failed_codegen.put(zcu.gpa, func.owner_nav, ng.err_msg.?); + try zcu.failed_codegen.put(gpa, func.owner_nav, ng.err_msg.?); ng.err_msg = null; return; }, @@ -1730,6 +1747,11 @@ pub const Object = struct { pcs_variable.setAlignment(Type.usize.abiAlignment(zcu).toLlvm(), &o.builder); pcs_variable.setSection(try o.builder.string("__sancov_pcs1"), &o.builder); try pcs_variable.setInitializer(init_val, &o.builder); + + try o.compiler_used.appendSlice(gpa, &.{ + f.counters_variable.toConst(&o.builder), + pcs_variable.toConst(&o.builder), + }); } try fg.wip.finish();