authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-25 15:56:57+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-25 17:37:27+01:00
log1e1598950aeb20e8f414fdb3993109f05f1b4765
tree80e2028257e69c9c4d44954d00fe18d51eb159d4
parent661137ac92ef05490a22dfcfb812a81a3014f0c7

llvm: implement per-module stripping

This avoids llvm module verification errors when the strip option is different across modules.

3 files changed, 69 insertions(+), 52 deletions(-)

src/Sema.zig+2-2
......@@ -6415,8 +6415,6 @@ fn zirDbgVar(
64156415 inst: Zir.Inst.Index,
64166416 air_tag: Air.Inst.Tag,
64176417) CompileError!void {
6418 if (block.is_comptime or block.ownerModule().strip) return;
6419
64206418 const str_op = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_op;
64216419 const operand = try sema.resolveInst(str_op.operand);
64226420 const name = str_op.getStr(sema.code);
......@@ -6430,6 +6428,8 @@ fn addDbgVar(
64306428 air_tag: Air.Inst.Tag,
64316429 name: []const u8,
64326430) CompileError!void {
6431 if (block.is_comptime or block.ownerModule().strip) return;
6432
64336433 const mod = sema.mod;
64346434 const operand_ty = sema.typeOf(operand);
64356435 const val_ty = switch (air_tag) {
src/codegen/llvm.zig+32-26
......@@ -837,11 +837,10 @@ pub const Object = struct {
837837 const gpa = comp.gpa;
838838 const target = comp.root_mod.resolved_target.result;
839839 const llvm_target_triple = try targetTriple(arena, target);
840 const strip = comp.root_mod.strip;
841840
842841 var builder = try Builder.init(.{
843842 .allocator = gpa,
844 .strip = strip,
843 .strip = comp.config.debug_format == .strip,
845844 .name = comp.root_name,
846845 .target = target,
847846 .triple = llvm_target_triple,
......@@ -1052,7 +1051,10 @@ pub const Object = struct {
10521051 const mod = o.module;
10531052 const errors_len = mod.global_error_set.count();
10541053
1055 var wip = try Builder.WipFunction.init(&o.builder, llvm_fn.ptrConst(&o.builder).kind.function);
1054 var wip = try Builder.WipFunction.init(&o.builder, .{
1055 .function = llvm_fn.ptrConst(&o.builder).kind.function,
1056 .strip = true,
1057 });
10561058 defer wip.deinit();
10571059 wip.cursor = .{ .block = try wip.block(0, "Entry") };
10581060
......@@ -1372,6 +1374,7 @@ pub const Object = struct {
13721374 air: Air,
13731375 liveness: Liveness,
13741376 ) !void {
1377 const comp = zcu.comp;
13751378 const func = zcu.funcInfo(func_index);
13761379 const decl_index = func.owner_decl;
13771380 const decl = zcu.declPtr(decl_index);
......@@ -1440,7 +1443,10 @@ pub const Object = struct {
14401443 function_index.setSection(try o.builder.string(section), &o.builder);
14411444
14421445 var deinit_wip = true;
1443 var wip = try Builder.WipFunction.init(&o.builder, function_index);
1446 var wip = try Builder.WipFunction.init(&o.builder, .{
1447 .function = function_index,
1448 .strip = owner_mod.strip,
1449 });
14441450 defer if (deinit_wip) wip.deinit();
14451451 wip.cursor = .{ .block = try wip.block(0, "Entry") };
14461452
......@@ -1459,8 +1465,6 @@ pub const Object = struct {
14591465 .unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
14601466 };
14611467
1462 const comp = zcu.comp;
1463
14641468 const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and
14651469 comp.config.any_error_tracing;
14661470
......@@ -1645,7 +1649,7 @@ pub const Object = struct {
16451649
16461650 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
16471651
1648 const file, const subprogram = if (!o.builder.strip) debug_info: {
1652 const file, const subprogram = if (!wip.strip) debug_info: {
16491653 const file = try o.getDebugFile(namespace.file_scope);
16501654
16511655 const line_number = decl.src_line + 1;
......@@ -4616,7 +4620,10 @@ pub const Object = struct {
46164620 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
46174621 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
46184622
4619 var wip = try Builder.WipFunction.init(&o.builder, function_index);
4623 var wip = try Builder.WipFunction.init(&o.builder, .{
4624 .function = function_index,
4625 .strip = true,
4626 });
46204627 defer wip.deinit();
46214628 wip.cursor = .{ .block = try wip.block(0, "Entry") };
46224629
......@@ -4686,23 +4693,23 @@ pub const DeclGen = struct {
46864693
46874694 fn genDecl(dg: *DeclGen) !void {
46884695 const o = dg.object;
4689 const mod = o.module;
4696 const zcu = o.module;
46904697 const decl = dg.decl;
46914698 const decl_index = dg.decl_index;
46924699 assert(decl.has_tv);
46934700
4694 if (decl.val.getExternFunc(mod)) |extern_func| {
4701 if (decl.val.getExternFunc(zcu)) |extern_func| {
46954702 _ = try o.resolveLlvmFunction(extern_func.decl);
46964703 } else {
46974704 const variable_index = try o.resolveGlobalDecl(decl_index);
46984705 variable_index.setAlignment(
4699 decl.getAlignment(mod).toLlvm(),
4706 decl.getAlignment(zcu).toLlvm(),
47004707 &o.builder,
47014708 );
4702 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
4709 if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
47034710 variable_index.setSection(try o.builder.string(section), &o.builder);
47044711 assert(decl.has_tv);
4705 const init_val = if (decl.val.getVariable(mod)) |decl_var| decl_var.init else init_val: {
4712 const init_val = if (decl.val.getVariable(zcu)) |decl_var| decl_var.init else init_val: {
47064713 variable_index.setMutability(.constant, &o.builder);
47074714 break :init_val decl.val.toIntern();
47084715 };
......@@ -4714,12 +4721,15 @@ pub const DeclGen = struct {
47144721 const line_number = decl.src_line + 1;
47154722 const is_internal_linkage = !o.module.decl_exports.contains(decl_index);
47164723
4717 if (dg.object.builder.strip) return;
4724 const namespace = zcu.namespacePtr(decl.src_namespace);
4725 const owner_mod = namespace.file_scope.mod;
47184726
4719 const debug_file = try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope);
4727 if (owner_mod.strip) return;
4728
4729 const debug_file = try o.getDebugFile(namespace.file_scope);
47204730
47214731 const debug_global_var = try o.builder.debugGlobalVar(
4722 try o.builder.metadataString(mod.intern_pool.stringToSlice(decl.name)), // Name
4732 try o.builder.metadataString(zcu.intern_pool.stringToSlice(decl.name)), // Name
47234733 try o.builder.metadataStringFromString(variable_index.name(&o.builder)), // Linkage name
47244734 debug_file, // File
47254735 debug_file, // Scope
......@@ -4735,7 +4745,7 @@ pub const DeclGen = struct {
47354745 debug_global_var,
47364746 debug_expression,
47374747 );
4738 if (!is_internal_linkage or decl.isExtern(mod))
4748 if (!is_internal_linkage or decl.isExtern(zcu))
47394749 variable_index.setGlobalVariableExpression(debug_global_var_expression, &o.builder);
47404750 try o.debug_globals.append(o.gpa, debug_global_var_expression);
47414751 }
......@@ -6570,7 +6580,6 @@ pub const FuncGen = struct {
65706580 }
65716581
65726582 fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6573 if (self.wip.builder.strip) return .none;
65746583 const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
65756584 self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);
65766585 self.prev_dbg_column = @intCast(dbg_stmt.column + 1);
......@@ -6593,7 +6602,6 @@ pub const FuncGen = struct {
65936602 }
65946603
65956604 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6596 if (self.wip.builder.strip) return .none;
65976605 const o = self.dg.object;
65986606 const zcu = o.module;
65996607
......@@ -6660,7 +6668,6 @@ pub const FuncGen = struct {
66606668 }
66616669
66626670 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
6663 if (self.wip.builder.strip) return .none;
66646671 const o = self.dg.object;
66656672
66666673 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
......@@ -6677,7 +6684,6 @@ pub const FuncGen = struct {
66776684 }
66786685
66796686 fn airDbgBlockBegin(self: *FuncGen) Allocator.Error!Builder.Value {
6680 if (self.wip.builder.strip) return .none;
66816687 const o = self.dg.object;
66826688
66836689 try self.scope_stack.append(self.gpa, self.scope);
......@@ -6693,13 +6699,11 @@ pub const FuncGen = struct {
66936699 }
66946700
66956701 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {
6696 if (self.wip.builder.strip) return .none;
66976702 self.scope = self.scope_stack.pop();
66986703 return .none;
66996704 }
67006705
67016706 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6702 if (self.wip.builder.strip) return .none;
67036707 const o = self.dg.object;
67046708 const mod = o.module;
67056709 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
......@@ -6732,7 +6736,6 @@ pub const FuncGen = struct {
67326736 }
67336737
67346738 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6735 if (self.wip.builder.strip) return .none;
67366739 const o = self.dg.object;
67376740 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
67386741 const operand = try self.resolveInst(pl_op.operand);
......@@ -8813,7 +8816,7 @@ pub const FuncGen = struct {
88138816 const arg_val = self.args[self.arg_index];
88148817 self.arg_index += 1;
88158818
8816 if (self.wip.builder.strip) return arg_val;
8819 if (self.wip.strip) return arg_val;
88178820
88188821 const inst_ty = self.typeOfIndex(inst);
88198822 if (needDbgVarWorkaround(o)) return arg_val;
......@@ -9660,7 +9663,10 @@ pub const FuncGen = struct {
96609663 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
96619664 gop.value_ptr.* = function_index;
96629665
9663 var wip = try Builder.WipFunction.init(&o.builder, function_index);
9666 var wip = try Builder.WipFunction.init(&o.builder, .{
9667 .function = function_index,
9668 .strip = true,
9669 });
96649670 defer wip.deinit();
96659671 wip.cursor = .{ .block = try wip.block(0, "Entry") };
96669672
src/codegen/llvm/Builder.zig+35-24
......@@ -3797,6 +3797,7 @@ pub const Function = struct {
37973797 instructions: std.MultiArrayList(Instruction) = .{},
37983798 names: [*]const String = &[0]String{},
37993799 value_indices: [*]const u32 = &[0]u32{},
3800 strip: bool,
38003801 debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, DebugLocation) = .{},
38013802 debug_values: []const Instruction.Index = &.{},
38023803 extra: []const u32 = &.{},
......@@ -4890,6 +4891,7 @@ pub const WipFunction = struct {
48904891 blocks: std.ArrayListUnmanaged(Block),
48914892 instructions: std.MultiArrayList(Instruction),
48924893 names: std.ArrayListUnmanaged(String),
4894 strip: bool,
48934895 debug_locations: std.AutoArrayHashMapUnmanaged(Instruction.Index, DebugLocation),
48944896 debug_values: std.AutoArrayHashMapUnmanaged(Instruction.Index, void),
48954897 extra: std.ArrayListUnmanaged(u32),
......@@ -4922,31 +4924,35 @@ pub const WipFunction = struct {
49224924
49234925 pub const Instruction = Function.Instruction;
49244926
4925 pub fn init(builder: *Builder, function: Function.Index) Allocator.Error!WipFunction {
4927 pub fn init(builder: *Builder, options: struct {
4928 function: Function.Index,
4929 strip: bool,
4930 }) Allocator.Error!WipFunction {
49264931 var self: WipFunction = .{
49274932 .builder = builder,
4928 .function = function,
4933 .function = options.function,
49294934 .prev_debug_location = .no_location,
49304935 .debug_location = .no_location,
49314936 .cursor = undefined,
49324937 .blocks = .{},
49334938 .instructions = .{},
49344939 .names = .{},
4940 .strip = options.strip,
49354941 .debug_locations = .{},
49364942 .debug_values = .{},
49374943 .extra = .{},
49384944 };
49394945 errdefer self.deinit();
49404946
4941 const params_len = function.typeOf(self.builder).functionParameters(self.builder).len;
4947 const params_len = options.function.typeOf(self.builder).functionParameters(self.builder).len;
49424948 try self.ensureUnusedExtraCapacity(params_len, NoExtra, 0);
49434949 try self.instructions.ensureUnusedCapacity(self.builder.gpa, params_len);
4944 if (!self.builder.strip) {
4950 if (!self.strip) {
49454951 try self.names.ensureUnusedCapacity(self.builder.gpa, params_len);
49464952 }
49474953 for (0..params_len) |param_index| {
49484954 self.instructions.appendAssumeCapacity(.{ .tag = .arg, .data = @intCast(param_index) });
4949 if (!self.builder.strip) {
4955 if (!self.strip) {
49504956 self.names.appendAssumeCapacity(.empty); // TODO: param names
49514957 }
49524958 }
......@@ -4967,7 +4973,7 @@ pub const WipFunction = struct {
49674973 try self.blocks.ensureUnusedCapacity(self.builder.gpa, 1);
49684974
49694975 const index: Block.Index = @enumFromInt(self.blocks.items.len);
4970 const final_name = if (self.builder.strip) .empty else try self.builder.string(name);
4976 const final_name = if (self.strip) .empty else try self.builder.string(name);
49714977 self.blocks.appendAssumeCapacity(.{
49724978 .name = final_name,
49734979 .incoming = incoming,
......@@ -5828,7 +5834,7 @@ pub const WipFunction = struct {
58285834 }
58295835
58305836 pub fn debugValue(self: *WipFunction, value: Value) Allocator.Error!Metadata {
5831 if (self.builder.strip) return .none;
5837 if (self.strip) return .none;
58325838 return switch (value.unwrap()) {
58335839 .instruction => |instr_index| blk: {
58345840 const gop = try self.debug_values.getOrPut(self.builder.gpa, instr_index);
......@@ -6015,7 +6021,7 @@ pub const WipFunction = struct {
60156021 value_index += 1;
60166022 function.instructions.appendAssumeCapacity(argument);
60176023 names[@intFromEnum(new_argument_index)] = try wip_name.map(
6018 if (self.builder.strip) .empty else self.names.items[@intFromEnum(old_argument_index)],
6024 if (self.strip) .empty else self.names.items[@intFromEnum(old_argument_index)],
60196025 ".",
60206026 );
60216027 if (self.debug_locations.get(old_argument_index)) |location| {
......@@ -6333,7 +6339,7 @@ pub const WipFunction = struct {
63336339 },
63346340 }
63356341 function.instructions.appendAssumeCapacity(instruction);
6336 names[@intFromEnum(new_instruction_index)] = try wip_name.map(if (self.builder.strip)
6342 names[@intFromEnum(new_instruction_index)] = try wip_name.map(if (self.strip)
63376343 if (old_instruction_index.hasResultWip(self)) .empty else .none
63386344 else
63396345 self.names.items[@intFromEnum(old_instruction_index)], ".");
......@@ -6356,6 +6362,7 @@ pub const WipFunction = struct {
63566362 function.blocks = blocks;
63576363 function.names = names.ptr;
63586364 function.value_indices = value_indices.ptr;
6365 function.strip = self.strip;
63596366 function.debug_locations = debug_locations;
63606367 function.debug_values = debug_values;
63616368 }
......@@ -6503,19 +6510,19 @@ pub const WipFunction = struct {
65036510 ) Allocator.Error!Instruction.Index {
65046511 const block_instructions = &self.cursor.block.ptr(self).instructions;
65056512 try self.instructions.ensureUnusedCapacity(self.builder.gpa, 1);
6506 if (!self.builder.strip) {
6513 if (!self.strip) {
65076514 try self.names.ensureUnusedCapacity(self.builder.gpa, 1);
65086515 try self.debug_locations.ensureUnusedCapacity(self.builder.gpa, 1);
65096516 }
65106517 try block_instructions.ensureUnusedCapacity(self.builder.gpa, 1);
65116518 const final_name = if (name) |n|
6512 if (self.builder.strip) .empty else try self.builder.string(n)
6519 if (self.strip) .empty else try self.builder.string(n)
65136520 else
65146521 .none;
65156522
65166523 const index: Instruction.Index = @enumFromInt(self.instructions.len);
65176524 self.instructions.appendAssumeCapacity(instruction);
6518 if (!self.builder.strip) {
6525 if (!self.strip) {
65196526 self.names.appendAssumeCapacity(final_name);
65206527 if (block_instructions.items.len == 0 or
65216528 !std.meta.eql(self.debug_location, self.prev_debug_location))
......@@ -8723,11 +8730,14 @@ pub fn addFunctionAssumeCapacity(
87238730) Function.Index {
87248731 assert(ty.isFunction(self));
87258732 const function_index: Function.Index = @enumFromInt(self.functions.items.len);
8726 self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
8727 .addr_space = addr_space,
8728 .type = ty,
8729 .kind = .{ .function = function_index },
8730 }) });
8733 self.functions.appendAssumeCapacity(.{
8734 .global = self.addGlobalAssumeCapacity(name, .{
8735 .addr_space = addr_space,
8736 .type = ty,
8737 .kind = .{ .function = function_index },
8738 }),
8739 .strip = undefined,
8740 });
87318741 return function_index;
87328742}
87338743
......@@ -14396,16 +14406,17 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1439614406 return @intCast(switch (value.unwrap()) {
1439714407 .instruction => |instruction| instruction.valueIndex(adapter.func) + adapter.firstInstr(),
1439814408 .constant => |constant| adapter.constant_adapter.getConstantIndex(constant),
14399 .metadata => |metadata| if (!adapter.metadata_adapter.builder.strip) blk: {
14409 .metadata => |metadata| {
14410 assert(!adapter.func.strip);
1440014411 const real_metadata = metadata.unwrap(adapter.metadata_adapter.builder);
1440114412 if (@intFromEnum(real_metadata) < Metadata.first_local_metadata)
14402 break :blk adapter.metadata_adapter.getMetadataIndex(real_metadata) - 1;
14413 return adapter.metadata_adapter.getMetadataIndex(real_metadata) - 1;
1440314414
1440414415 return @intCast(@intFromEnum(metadata) -
1440514416 Metadata.first_local_metadata +
1440614417 adapter.metadata_adapter.builder.metadata_string_map.count() - 1 +
1440714418 adapter.metadata_adapter.builder.metadata_map.count() - 1);
14408 } else unreachable,
14419 },
1440914420 });
1441014421 }
1441114422
......@@ -14452,7 +14463,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1445214463 var adapter = FunctionAdapter.init(constant_adapter, metadata_adapter, &func);
1445314464
1445414465 // Emit function level metadata block
14455 if (!self.strip and func.debug_values.len != 0) {
14466 if (!func.strip and func.debug_values.len > 0) {
1445614467 const MetadataBlock = ir.FunctionMetadataBlock;
1445714468 var metadata_block = try function_block.enterSubBlock(MetadataBlock);
1445814469
......@@ -14913,7 +14924,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1491314924 },
1491414925 }
1491514926
14916 if (!self.strip) {
14927 if (!func.strip) {
1491714928 if (func.debug_locations.get(@enumFromInt(instr_index))) |debug_location| {
1491814929 switch (debug_location) {
1491914930 .no_location => has_location = false,
......@@ -14937,7 +14948,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1493714948 }
1493814949
1493914950 // VALUE_SYMTAB
14940 if (!self.strip) {
14951 if (!func.strip) {
1494114952 const ValueSymbolTable = ir.FunctionValueSymbolTable;
1494214953
1494314954 var value_symtab_block = try function_block.enterSubBlock(ValueSymbolTable);
......@@ -14959,7 +14970,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1495914970 }
1496014971
1496114972 // METADATA_ATTACHMENT_BLOCK
14962 if (!self.strip) blk: {
14973 if (!func.strip) blk: {
1496314974 const dbg = func.global.ptrConst(self).dbg;
1496414975
1496514976 if (dbg == .none) break :blk;