Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PIC/PIE tests and fix some bugs + some improvements to the test harness #22067

Merged
merged 13 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ pub fn build(b: *std.Build) !void {
test_step.dependOn(check_fmt);

const test_cases_step = b.step("test-cases", "Run the main compiler test cases");
try tests.addCases(b, test_cases_step, test_filters, target, .{
try tests.addCases(b, test_cases_step, test_filters, test_target_filters, target, .{
.skip_translate_c = skip_translate_c,
.skip_run_translated_c = skip_run_translated_c,
}, .{
Expand Down Expand Up @@ -541,13 +541,18 @@ pub fn build(b: *std.Build) !void {
enable_ios_sdk,
enable_symlinks_windows,
));
test_step.dependOn(tests.addCAbiTests(b, skip_non_native, skip_release));
test_step.dependOn(tests.addCAbiTests(b, .{
.test_target_filters = test_target_filters,
.skip_non_native = skip_non_native,
.skip_release = skip_release,
}));
test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, enable_ios_sdk, enable_symlinks_windows));
test_step.dependOn(tests.addStackTraceTests(b, test_filters, optimization_modes));
test_step.dependOn(tests.addCliTests(b));
test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filters, optimization_modes));
if (tests.addDebuggerTests(b, .{
.test_filters = test_filters,
.test_target_filters = test_target_filters,
.gdb = b.option([]const u8, "gdb", "path to gdb binary"),
.lldb = b.option([]const u8, "lldb", "path to lldb binary"),
.optimize_modes = optimization_modes,
Expand Down
5 changes: 5 additions & 0 deletions lib/std/Build/Cache.zig
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ pub const HashHelper = struct {
},
std.Target.Os.TaggedVersionRange => {
switch (x) {
.hurd => |hurd| {
hh.add(hurd.range.min);
hh.add(hurd.range.max);
hh.add(hurd.glibc);
},
.linux => |linux| {
hh.add(linux.range.min);
hh.add(linux.range.max);
Expand Down
43 changes: 38 additions & 5 deletions lib/std/Target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ pub const Os = struct {
.hermit,

.aix,
.hurd,
.rtems,
.zos,

Expand Down Expand Up @@ -218,6 +217,7 @@ pub const Os = struct {
.vulkan,
=> .semver,

.hurd => .hurd,
.linux => .linux,

.windows => .windows,
Expand Down Expand Up @@ -356,6 +356,21 @@ pub const Os = struct {
}
};

pub const HurdVersionRange = struct {
range: std.SemanticVersion.Range,
glibc: std.SemanticVersion,

pub inline fn includesVersion(range: HurdVersionRange, ver: std.SemanticVersion) bool {
return range.range.includesVersion(ver);
}

/// Checks if system is guaranteed to be at least `version` or older than `version`.
/// Returns `null` if a runtime check is required.
pub inline fn isAtLeast(range: HurdVersionRange, ver: std.SemanticVersion) ?bool {
return range.range.isAtLeast(ver);
}
};

pub const LinuxVersionRange = struct {
range: std.SemanticVersion.Range,
glibc: std.SemanticVersion,
Expand Down Expand Up @@ -400,6 +415,7 @@ pub const Os = struct {
pub const VersionRange = union {
none: void,
semver: std.SemanticVersion.Range,
hurd: HurdVersionRange,
linux: LinuxVersionRange,
windows: WindowsVersion.Range,

Expand Down Expand Up @@ -456,9 +472,12 @@ pub const Os = struct {
},
},
.hurd => .{
.semver = .{
.min = .{ .major = 0, .minor = 9, .patch = 0 },
.max = .{ .major = 0, .minor = 9, .patch = 0 },
.hurd = .{
.range = .{
.min = .{ .major = 0, .minor = 9, .patch = 0 },
.max = .{ .major = 0, .minor = 9, .patch = 0 },
},
.glibc = .{ .major = 2, .minor = 28, .patch = 0 },
},
},
.linux => .{
Expand Down Expand Up @@ -632,8 +651,17 @@ pub const Os = struct {
pub const TaggedVersionRange = union(enum) {
none: void,
semver: std.SemanticVersion.Range,
hurd: HurdVersionRange,
linux: LinuxVersionRange,
windows: WindowsVersion.Range,

pub fn gnuLibCVersion(range: TaggedVersionRange) ?std.SemanticVersion {
return switch (range) {
.none, .semver, .windows => null,
.hurd => |h| h.glibc,
.linux => |l| l.glibc,
};
}
};

/// Provides a tagged union. `Target` does not store the tag because it is
Expand All @@ -642,6 +670,7 @@ pub const Os = struct {
return switch (os.tag.versionRangeTag()) {
.none => .{ .none = {} },
.semver => .{ .semver = os.version_range.semver },
.hurd => .{ .hurd = os.version_range.hurd },
.linux => .{ .linux = os.version_range.linux },
.windows => .{ .windows = os.version_range.windows },
};
Expand All @@ -651,12 +680,13 @@ pub const Os = struct {
/// Returns `null` if a runtime check is required.
pub inline fn isAtLeast(os: Os, comptime tag: Tag, ver: switch (tag.versionRangeTag()) {
.none => void,
.semver, .linux => std.SemanticVersion,
.semver, .hurd, .linux => std.SemanticVersion,
.windows => WindowsVersion,
}) ?bool {
return if (os.tag != tag) false else switch (tag.versionRangeTag()) {
.none => true,
inline .semver,
.hurd,
.linux,
.windows,
=> |field| @field(os.version_range, @tagName(field)).isAtLeast(ver),
Expand Down Expand Up @@ -832,6 +862,9 @@ pub const Abi = enum {
.mips,
.mipsel,
=> .musleabi,
.mips64,
.mips64el,
=> .muslabi64,
else => .musl,
},
.rtems => switch (arch) {
Expand Down
10 changes: 5 additions & 5 deletions lib/std/Target/Query.zig
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub fn fromTarget(target: Target) Query {
.os_version_min = undefined,
.os_version_max = undefined,
.abi = target.abi,
.glibc_version = if (target.isGnuLibC()) target.os.version_range.linux.glibc else null,
.glibc_version = target.os.versionRange().gnuLibCVersion(),
.android_api_level = if (target.abi.isAndroid()) target.os.version_range.linux.android else null,
};
result.updateOsVersionRange(target.os);
Expand Down Expand Up @@ -132,9 +132,9 @@ fn updateOsVersionRange(self: *Query, os: Target.Os) void {
.{ .semver = os.version_range.semver.min },
.{ .semver = os.version_range.semver.max },
},
.linux => .{
.{ .semver = os.version_range.linux.range.min },
.{ .semver = os.version_range.linux.range.max },
inline .hurd, .linux => |t| .{
.{ .semver = @field(os.version_range, @tagName(t)).range.min },
.{ .semver = @field(os.version_range, @tagName(t)).range.max },
},
.windows => .{
.{ .windows = os.version_range.windows.min },
Expand Down Expand Up @@ -544,7 +544,7 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !
const version_text = it.rest();
if (version_text.len > 0) switch (tag.versionRangeTag()) {
.none => return error.InvalidOperatingSystemVersion,
.semver, .linux => range: {
.semver, .hurd, .linux => range: {
var range_it = mem.splitSequence(u8, version_text, "...");
result.os_version_min = .{
.semver = parseVersion(range_it.first()) catch |err| switch (err) {
Expand Down
5 changes: 2 additions & 3 deletions lib/std/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ pub inline fn versionCheck(comptime version: std.SemanticVersion) bool {
if (!builtin.link_libc) break :blk false;
if (native_abi.isMusl()) break :blk true;
if (builtin.target.isGnuLibC()) {
const ver = builtin.os.version_range.linux.glibc;
const order = ver.order(version);
break :blk switch (order) {
const ver = builtin.os.versionRange().gnuLibCVersion().?;
break :blk switch (ver.order(version)) {
.gt, .eq => true,
.lt => false,
};
Expand Down
2 changes: 1 addition & 1 deletion lib/std/os/linux/pie.zig
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ inline fn getDynamicSymbol() [*]elf.Dyn {
\\ .hidden _DYNAMIC
\\ larl %[ret], 1f
\\ ag %[ret], 0(%[ret])
\\ b 2f
\\ jg 2f
\\ 1: .quad _DYNAMIC - .
\\ 2:
: [ret] "=r" (-> [*]elf.Dyn),
Expand Down
13 changes: 8 additions & 5 deletions lib/std/zig/system.zig
Original file line number Diff line number Diff line change
Expand Up @@ -311,24 +311,27 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {

if (query.os_version_min) |min| switch (min) {
.none => {},
.semver => |semver| switch (os.tag) {
.linux => os.version_range.linux.range.min = semver,
.semver => |semver| switch (os.tag.versionRangeTag()) {
inline .hurd, .linux => |t| @field(os.version_range, @tagName(t)).range.min = semver,
else => os.version_range.semver.min = semver,
},
.windows => |win_ver| os.version_range.windows.min = win_ver,
};

if (query.os_version_max) |max| switch (max) {
.none => {},
.semver => |semver| switch (os.tag) {
.linux => os.version_range.linux.range.max = semver,
.semver => |semver| switch (os.tag.versionRangeTag()) {
inline .hurd, .linux => |t| @field(os.version_range, @tagName(t)).range.max = semver,
else => os.version_range.semver.max = semver,
},
.windows => |win_ver| os.version_range.windows.max = win_ver,
};

if (query.glibc_version) |glibc| {
os.version_range.linux.glibc = glibc;
switch (os.tag.versionRangeTag()) {
inline .hurd, .linux => |t| @field(os.version_range, @tagName(t)).glibc = glibc,
else => {},
}
}

if (query.android_api_level) |android| {
Expand Down
4 changes: 2 additions & 2 deletions lib/std/zig/target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ pub fn canBuildLibC(target: std.Target) bool {
const ver = target.os.version_range.semver;
return ver.min.order(libc.os_ver.?) != .lt;
}
// Ensure glibc (aka *-linux-gnu) version is supported
// Ensure glibc (aka *-(linux,hurd)-gnu) version is supported
if (target.isGnuLibC()) {
const min_glibc_ver = libc.glibc_min orelse return true;
const target_glibc_ver = target.os.version_range.linux.glibc;
const target_glibc_ver = target.os.versionRange().gnuLibCVersion().?;
return target_glibc_ver.order(min_glibc_ver) != .lt;
}
return true;
Expand Down
34 changes: 34 additions & 0 deletions src/Builtin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,40 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {

linux.android,
}),
.hurd => |hurd| try buffer.writer().print(
\\ .hurd = .{{
\\ .range = .{{
\\ .min = .{{
\\ .major = {},
\\ .minor = {},
\\ .patch = {},
\\ }},
\\ .max = .{{
\\ .major = {},
\\ .minor = {},
\\ .patch = {},
\\ }},
\\ }},
\\ .glibc = .{{
\\ .major = {},
\\ .minor = {},
\\ .patch = {},
\\ }},
\\ }}}},
\\
, .{
hurd.range.min.major,
hurd.range.min.minor,
hurd.range.min.patch,

hurd.range.max.major,
hurd.range.max.minor,
hurd.range.max.patch,

hurd.glibc.major,
hurd.glibc.minor,
hurd.glibc.patch,
}),
.windows => |windows| try buffer.writer().print(
\\ .windows = .{{
\\ .min = {c},
Expand Down
2 changes: 1 addition & 1 deletion src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5315,7 +5315,7 @@ pub fn addCCArgs(

if (comp.config.link_libc) {
if (target.isGnuLibC()) {
const target_version = target.os.version_range.linux.glibc;
const target_version = target.os.versionRange().gnuLibCVersion().?;
const glibc_minor_define = try std.fmt.allocPrint(arena, "-D__GLIBC_MINOR__={d}", .{
target_version.minor,
});
Expand Down
16 changes: 10 additions & 6 deletions src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
ver.min.minor,
ver.min.patch,
}),
.linux => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{
inline .linux, .hurd => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{
ver.range.min.major,
ver.range.min.minor,
ver.range.min.patch,
Expand Down Expand Up @@ -290,11 +290,15 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
.semver,
.windows,
=> {},
.linux => |ver| if (target.abi.isGnu()) try llvm_triple.writer().print("{d}.{d}.{d}", .{
ver.glibc.major,
ver.glibc.minor,
ver.glibc.patch,
}) else if (target.abi.isAndroid()) try llvm_triple.writer().print("{d}", .{ver.android}),
inline .hurd, .linux => |ver| if (target.abi.isGnu()) {
try llvm_triple.writer().print("{d}.{d}.{d}", .{
ver.glibc.major,
ver.glibc.minor,
ver.glibc.patch,
});
} else if (@TypeOf(ver) == std.Target.Os.LinuxVersionRange and target.abi.isAndroid()) {
try llvm_triple.writer().print("{d}", .{ver.android});
},
}

return llvm_triple.toOwnedSlice();
Expand Down
6 changes: 3 additions & 3 deletions src/glibc.zig
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
const arena = arena_allocator.allocator();

const target = comp.root_mod.resolved_target.result;
const target_ver = target.os.version_range.linux.glibc;
const target_ver = target.os.versionRange().gnuLibCVersion().?;
const nonshared_stat = target_ver.order(.{ .major = 2, .minor = 32, .patch = 0 }) != .gt;
const start_old_init_fini = target_ver.order(.{ .major = 2, .minor = 33, .patch = 0 }) != .gt;

Expand Down Expand Up @@ -750,7 +750,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
const arena = arena_allocator.allocator();

const target = comp.getTarget();
const target_version = target.os.version_range.linux.glibc;
const target_version = target.os.versionRange().gnuLibCVersion().?;

// Use the global cache directory.
var cache: Cache = .{
Expand Down Expand Up @@ -1218,7 +1218,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi
}

fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
const target_version = comp.getTarget().os.version_range.linux.glibc;
const target_version = comp.getTarget().os.versionRange().gnuLibCVersion().?;

assert(comp.glibc_so_files == null);
comp.glibc_so_files = so_files;
Expand Down
6 changes: 3 additions & 3 deletions src/libcxx.zig
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: std.Progress.Node) BuildError!

if (target.isGnuLibC()) {
// glibc 2.16 introduced aligned_alloc
if (target.os.version_range.linux.glibc.order(.{ .major = 2, .minor = 16, .patch = 0 }) == .lt) {
if (target.os.versionRange().gnuLibCVersion().?.order(.{ .major = 2, .minor = 16, .patch = 0 }) == .lt) {
try cflags.append("-D_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION");
}
}
Expand Down Expand Up @@ -477,7 +477,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
}
try cflags.append("-D_LIBCXXABI_HAS_NO_THREADS");
} else if (target.abi.isGnu()) {
if (target.os.tag != .linux or !(target.os.version_range.linux.glibc.order(.{ .major = 2, .minor = 18, .patch = 0 }) == .lt))
if (target.os.tag != .linux or !(target.os.versionRange().gnuLibCVersion().?.order(.{ .major = 2, .minor = 18, .patch = 0 }) == .lt))
try cflags.append("-DHAVE___CXA_THREAD_ATEXIT_IMPL");
}

Expand All @@ -500,7 +500,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr

if (target.isGnuLibC()) {
// glibc 2.16 introduced aligned_alloc
if (target.os.version_range.linux.glibc.order(.{ .major = 2, .minor = 16, .patch = 0 }) == .lt) {
if (target.os.versionRange().gnuLibCVersion().?.order(.{ .major = 2, .minor = 16, .patch = 0 }) == .lt) {
try cflags.append("-D_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/link/Elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2013,7 +2013,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
} else if (target.isGnuLibC()) {
for (glibc.libs) |lib| {
if (lib.removed_in) |rem_in| {
if (target.os.version_range.linux.glibc.order(rem_in) != .lt) continue;
if (target.os.versionRange().gnuLibCVersion().?.order(rem_in) != .lt) continue;
}

const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
Expand Down
1 change: 1 addition & 0 deletions test/cases/inherit_want_safety.zig
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ pub export fn entry() usize {

// compile
// output_mode=Obj
// emit_bin=false
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI @andrewrk 5beb5f2 you'll probably want to revert this one once you finish your current wasm linker work.

Loading
Loading