From 629bd90e267691acac7625771bb47de4298aa8aa Mon Sep 17 00:00:00 2001 From: antlilja Date: Sun, 1 Sep 2024 14:10:56 +0200 Subject: [PATCH 1/4] LLVM: Emit module flags through Builder instead of LLVM API --- src/codegen/llvm.zig | 138 +++++++++++++++++++---------------- src/codegen/llvm/Builder.zig | 14 ++-- 2 files changed, 83 insertions(+), 69 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index dc8996afda08..14571b9d8fda 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -898,58 +898,7 @@ pub const Object = struct { .{ .optimized = comp.root_mod.optimize_mode != .Debug }, ); - const i32_2 = try builder.intConst(.i32, 2); - const i32_3 = try builder.intConst(.i32, 3); - const debug_info_version = try builder.debugModuleFlag( - try builder.metadataConstant(i32_2), - try builder.metadataString("Debug Info Version"), - try builder.metadataConstant(i32_3), - ); - - switch (comp.config.debug_format) { - .strip => unreachable, - .dwarf => |f| { - const i32_4 = try builder.intConst(.i32, 4); - const dwarf_version = try builder.debugModuleFlag( - try builder.metadataConstant(i32_2), - try builder.metadataString("Dwarf Version"), - try builder.metadataConstant(i32_4), - ); - switch (f) { - .@"32" => { - try builder.debugNamed(try builder.metadataString("llvm.module.flags"), &.{ - debug_info_version, - dwarf_version, - }); - }, - .@"64" => { - const dwarf64 = try builder.debugModuleFlag( - try builder.metadataConstant(i32_2), - try builder.metadataString("DWARF64"), - try builder.metadataConstant(.@"1"), - ); - try builder.debugNamed(try builder.metadataString("llvm.module.flags"), &.{ - debug_info_version, - dwarf_version, - dwarf64, - }); - }, - } - }, - .code_view => { - const code_view = try builder.debugModuleFlag( - try builder.metadataConstant(i32_2), - try builder.metadataString("CodeView"), - try builder.metadataConstant(.@"1"), - ); - try builder.debugNamed(try builder.metadataString("llvm.module.flags"), &.{ - debug_info_version, - code_view, - }); - }, - } - - try builder.debugNamed(try builder.metadataString("llvm.dbg.cu"), &.{debug_compile_unit}); + try builder.metadataNamed(try builder.metadataString("llvm.dbg.cu"), &.{debug_compile_unit}); break :debug_info .{ debug_compile_unit, debug_enums_fwd_ref, debug_globals_fwd_ref }; } else .{.none} ** 3; @@ -1149,6 +1098,81 @@ pub const Object = struct { } } + { + var module_flags = try std.ArrayList(Builder.Metadata).initCapacity(o.gpa, 6); + defer module_flags.deinit(); + + const behavior_warning = try o.builder.metadataConstant(try o.builder.intConst(.i32, 2)); + + const large_pic = target_util.usesLargePIC(comp.root_mod.resolved_target.result); + if (comp.root_mod.pic) { + module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( + behavior_warning, + try o.builder.metadataString("PIC Level"), + try o.builder.metadataConstant(try o.builder.intConst(.i32, @as(i32, if (large_pic) 2 else 1))), + )); + } + + if (comp.config.pie) { + module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( + behavior_warning, + try o.builder.metadataString("PIE Level"), + try o.builder.metadataConstant(try o.builder.intConst(.i32, @as(i32, if (large_pic) 2 else 1))), + )); + } + + if (comp.root_mod.code_model != .default) { + module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( + behavior_warning, + try o.builder.metadataString("Code Model"), + try o.builder.metadataConstant(try o.builder.intConst(.i32, @as(i32, switch (comp.root_mod.code_model) { + .tiny => 0, + .small => 1, + .kernel => 2, + .medium => 3, + .large => 4, + else => unreachable, + }))), + )); + } + + if (!o.builder.strip) { + module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( + behavior_warning, + try o.builder.metadataString("Debug Info Version"), + try o.builder.metadataConstant(try o.builder.intConst(.i32, 3)), + )); + + switch (comp.config.debug_format) { + .strip => unreachable, + .dwarf => |f| { + module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( + behavior_warning, + try o.builder.metadataString("Dwarf Version"), + try o.builder.metadataConstant(try o.builder.intConst(.i32, 4)), + )); + + if (f == .@"64") { + module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( + behavior_warning, + try o.builder.metadataString("DWARF64"), + try o.builder.metadataConstant(.@"1"), + )); + } + }, + .code_view => { + module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( + behavior_warning, + try o.builder.metadataString("CodeView"), + try o.builder.metadataConstant(.@"1"), + )); + }, + } + } + + try o.builder.metadataNamed(try o.builder.metadataString("llvm.module.flags"), module_flags.items); + } + const target_triple_sentinel = try o.gpa.dupeZ(u8, o.builder.target_triple.slice(&o.builder).?); defer o.gpa.free(target_triple_sentinel); @@ -1235,14 +1259,13 @@ pub const Object = struct { } const optimize_mode = comp.root_mod.optimize_mode; - const pic = comp.root_mod.pic; const opt_level: llvm.CodeGenOptLevel = if (optimize_mode == .Debug) .None else .Aggressive; - const reloc_mode: llvm.RelocMode = if (pic) + const reloc_mode: llvm.RelocMode = if (comp.root_mod.pic) .PIC else if (comp.config.link_mode == .dynamic) llvm.RelocMode.DynamicNoPIC @@ -1276,13 +1299,6 @@ pub const Object = struct { ); errdefer target_machine.dispose(); - const large_pic = target_util.usesLargePIC(comp.root_mod.resolved_target.result); - - if (pic) module.setModulePICLevel(large_pic); - if (comp.config.pie) module.setModulePIELevel(large_pic); - - if (code_model != .Default) module.setModuleCodeModel(code_model); - if (comp.llvm_opt_bisect_limit >= 0) { context.setOptBisectLimit(comp.llvm_opt_bisect_limit); } diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index 029b81dc3f75..9b281266047d 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -11899,10 +11899,10 @@ pub fn trailingMetadataStringAssumeCapacity(self: *Builder) MetadataString { return @enumFromInt(gop.index); } -pub fn debugNamed(self: *Builder, name: MetadataString, operands: []const Metadata) Allocator.Error!void { +pub fn metadataNamed(self: *Builder, name: MetadataString, operands: []const Metadata) Allocator.Error!void { try self.metadata_extra.ensureUnusedCapacity(self.gpa, operands.len); try self.metadata_named.ensureUnusedCapacity(self.gpa, 1); - self.debugNamedAssumeCapacity(name, operands); + self.metadataNamedAssumeCapacity(name, operands); } fn metadataNone(self: *Builder) Allocator.Error!Metadata { @@ -12213,14 +12213,14 @@ pub fn strTuple( return self.strTupleAssumeCapacity(str, elements); } -pub fn debugModuleFlag( +pub fn metadataModuleFlag( self: *Builder, behavior: Metadata, name: MetadataString, constant: Metadata, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.ModuleFlag, 0); - return self.debugModuleFlagAssumeCapacity(behavior, name, constant); + return self.metadataModuleFlagAssumeCapacity(behavior, name, constant); } pub fn debugLocalVar( @@ -12365,8 +12365,7 @@ fn metadataDistinctAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anyt return @enumFromInt(gop.index); } -fn debugNamedAssumeCapacity(self: *Builder, name: MetadataString, operands: []const Metadata) void { - assert(!self.strip); +fn metadataNamedAssumeCapacity(self: *Builder, name: MetadataString, operands: []const Metadata) void { assert(name != .none); const extra_index: u32 = @intCast(self.metadata_extra.items.len); self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(operands)); @@ -12949,13 +12948,12 @@ fn strTupleAssumeCapacity( return @enumFromInt(gop.index); } -fn debugModuleFlagAssumeCapacity( +fn metadataModuleFlagAssumeCapacity( self: *Builder, behavior: Metadata, name: MetadataString, constant: Metadata, ) Metadata { - assert(!self.strip); return self.metadataSimpleAssumeCapacity(.module_flag, Metadata.ModuleFlag{ .behavior = behavior, .name = name, From 7cb87c14fe593b60b7034f12d2efd927309a0b96 Mon Sep 17 00:00:00 2001 From: antlilja Date: Sun, 1 Sep 2024 14:21:19 +0200 Subject: [PATCH 2/4] LLVM: Remove cpp bindings for setPICLevel, setPIELevel and setCodeModel --- src/codegen/llvm/bindings.zig | 9 --------- src/zig_llvm.cpp | 14 -------------- src/zig_llvm.h | 4 ---- 3 files changed, 27 deletions(-) diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index d21fc69ff3be..a002dbcd8a53 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -51,15 +51,6 @@ pub const Context = opaque { pub const Module = opaque { pub const dispose = LLVMDisposeModule; extern fn LLVMDisposeModule(*Module) void; - - pub const setModulePICLevel = ZigLLVMSetModulePICLevel; - extern fn ZigLLVMSetModulePICLevel(module: *Module, big: bool) void; - - pub const setModulePIELevel = ZigLLVMSetModulePIELevel; - extern fn ZigLLVMSetModulePIELevel(module: *Module, large: bool) void; - - pub const setModuleCodeModel = ZigLLVMSetModuleCodeModel; - extern fn ZigLLVMSetModuleCodeModel(module: *Module, code_model: CodeModel) void; }; pub const disposeMessage = LLVMDisposeMessage; diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index dd0243b66089..351b28df6b58 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -435,20 +435,6 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) { cl::ParseCommandLineOptions(argc, argv); } -void ZigLLVMSetModulePICLevel(LLVMModuleRef module, bool big) { - unwrap(module)->setPICLevel(big ? PICLevel::Level::BigPIC : PICLevel::Level::SmallPIC); -} - -void ZigLLVMSetModulePIELevel(LLVMModuleRef module, bool large) { - unwrap(module)->setPIELevel(large ? PIELevel::Level::Large : PIELevel::Level::Small); -} - -void ZigLLVMSetModuleCodeModel(LLVMModuleRef module, LLVMCodeModel code_model) { - bool JIT; - unwrap(module)->setCodeModel(*unwrap(code_model, JIT)); - assert(!JIT); -} - bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch, const char *output_lib_path, bool kill_at) { diff --git a/src/zig_llvm.h b/src/zig_llvm.h index a88183c2cc9d..e831e9cf8bae 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -155,10 +155,6 @@ enum ZigLLVM_CallingConv { ZigLLVM_MaxID = 1023, }; -ZIG_EXTERN_C void ZigLLVMSetModulePICLevel(LLVMModuleRef module, bool big); -ZIG_EXTERN_C void ZigLLVMSetModulePIELevel(LLVMModuleRef module, bool large); -ZIG_EXTERN_C void ZigLLVMSetModuleCodeModel(LLVMModuleRef module, LLVMCodeModel code_model); - ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv); // synchronize with llvm/include/ADT/Triple.h::ArchType From 76908da3ac2f4ba64a80d6618211e7390995c00e Mon Sep 17 00:00:00 2001 From: antlilja Date: Sun, 1 Sep 2024 14:43:30 +0200 Subject: [PATCH 3/4] LLVM: Set module flag behaviors to match what LLVM and clang does --- src/codegen/llvm.zig | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 14571b9d8fda..222845d32ec9 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1102,12 +1102,15 @@ pub const Object = struct { var module_flags = try std.ArrayList(Builder.Metadata).initCapacity(o.gpa, 6); defer module_flags.deinit(); + const behavior_error = try o.builder.metadataConstant(try o.builder.intConst(.i32, 1)); const behavior_warning = try o.builder.metadataConstant(try o.builder.intConst(.i32, 2)); + const behavior_max = try o.builder.metadataConstant(try o.builder.intConst(.i32, 7)); + const behavior_min = try o.builder.metadataConstant(try o.builder.intConst(.i32, 8)); const large_pic = target_util.usesLargePIC(comp.root_mod.resolved_target.result); if (comp.root_mod.pic) { module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( - behavior_warning, + behavior_min, try o.builder.metadataString("PIC Level"), try o.builder.metadataConstant(try o.builder.intConst(.i32, @as(i32, if (large_pic) 2 else 1))), )); @@ -1115,7 +1118,7 @@ pub const Object = struct { if (comp.config.pie) { module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( - behavior_warning, + behavior_max, try o.builder.metadataString("PIE Level"), try o.builder.metadataConstant(try o.builder.intConst(.i32, @as(i32, if (large_pic) 2 else 1))), )); @@ -1123,7 +1126,7 @@ pub const Object = struct { if (comp.root_mod.code_model != .default) { module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( - behavior_warning, + behavior_error, try o.builder.metadataString("Code Model"), try o.builder.metadataConstant(try o.builder.intConst(.i32, @as(i32, switch (comp.root_mod.code_model) { .tiny => 0, @@ -1147,14 +1150,14 @@ pub const Object = struct { .strip => unreachable, .dwarf => |f| { module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( - behavior_warning, + behavior_max, try o.builder.metadataString("Dwarf Version"), try o.builder.metadataConstant(try o.builder.intConst(.i32, 4)), )); if (f == .@"64") { module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( - behavior_warning, + behavior_max, try o.builder.metadataString("DWARF64"), try o.builder.metadataConstant(.@"1"), )); From 15b4c01ab1dd578b0a306b18b11b79f6b9bce88d Mon Sep 17 00:00:00 2001 From: antlilja Date: Sun, 1 Sep 2024 15:09:25 +0200 Subject: [PATCH 4/4] Rename usesLargePIC to picLevel and return the PIC level --- src/codegen/llvm.zig | 6 +++--- src/target.zig | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 222845d32ec9..6915e9a2ac7e 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1107,12 +1107,12 @@ pub const Object = struct { const behavior_max = try o.builder.metadataConstant(try o.builder.intConst(.i32, 7)); const behavior_min = try o.builder.metadataConstant(try o.builder.intConst(.i32, 8)); - const large_pic = target_util.usesLargePIC(comp.root_mod.resolved_target.result); + const pic_level = target_util.picLevel(comp.root_mod.resolved_target.result); if (comp.root_mod.pic) { module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( behavior_min, try o.builder.metadataString("PIC Level"), - try o.builder.metadataConstant(try o.builder.intConst(.i32, @as(i32, if (large_pic) 2 else 1))), + try o.builder.metadataConstant(try o.builder.intConst(.i32, pic_level)), )); } @@ -1120,7 +1120,7 @@ pub const Object = struct { module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag( behavior_max, try o.builder.metadataString("PIE Level"), - try o.builder.metadataConstant(try o.builder.intConst(.i32, @as(i32, if (large_pic) 2 else 1))), + try o.builder.metadataConstant(try o.builder.intConst(.i32, pic_level)), )); } diff --git a/src/target.zig b/src/target.zig index 9147347f9357..bc2ba4c8316f 100644 --- a/src/target.zig +++ b/src/target.zig @@ -49,10 +49,10 @@ pub fn requiresPIC(target: std.Target, linking_libc: bool) bool { (target.abi == .ohos and target.cpu.arch == .aarch64); } -pub fn usesLargePIC(target: std.Target) bool { +pub fn picLevel(target: std.Target) u32 { // MIPS always uses PIC level 1; other platforms vary in their default PIC levels, but they // support both level 1 and 2, in which case we prefer 2. - return !target.cpu.arch.isMIPS(); + return if (target.cpu.arch.isMIPS()) 1 else 2; } /// This is not whether the target supports Position Independent Code, but whether the -fPIC