authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-20 16:41:58-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-06-20 16:41:58-07:00
logb77679039fd40aa1693781f99ac89f2dc705e5c2
treee3a4d2e77f3e4e31b3c854a6ffe010f1cb35e8b5
parent0f2339f55b2fa45a8af94c26a7ceb8377e3acfef
parentc205521aea01e332209a28e7518a787d1c1e8f26
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #15415 from ehaas/c-char-signedness

Set `c_char` signedness based on the target

6 files changed, 44 insertions(+), 5 deletions(-)

lib/std/target.zig+26
...@@ -1910,6 +1910,32 @@ pub const Target = struct {...@@ -1910,6 +1910,32 @@ pub const Target = struct {
1910 }1910 }
1911 }1911 }
19121912
1913 /// Default signedness of `char` for the native C compiler for this target
1914 /// Note that char signedness is implementation-defined and many compilers provide
1915 /// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char
1916 pub fn charSignedness(target: Target) std.builtin.Signedness {
1917 switch (target.cpu.arch) {
1918 .aarch64,
1919 .aarch64_32,
1920 .aarch64_be,
1921 .arm,
1922 .armeb,
1923 .thumb,
1924 .thumbeb,
1925 => return if (target.os.tag.isDarwin() or target.os.tag == .windows) .signed else .unsigned,
1926 .powerpc, .powerpc64 => return if (target.os.tag.isDarwin()) .signed else .unsigned,
1927 .powerpc64le,
1928 .s390x,
1929 .xcore,
1930 .arc,
1931 .msp430,
1932 .riscv32,
1933 .riscv64,
1934 => return .unsigned,
1935 else => return .signed,
1936 }
1937 }
1938
1913 pub const CType = enum {1939 pub const CType = enum {
1914 char,1940 char,
1915 short,1941 short,
src/codegen/c.zig+1-1
...@@ -1880,7 +1880,7 @@ pub const DeclGen = struct {...@@ -1880,7 +1880,7 @@ pub const DeclGen = struct {
1880 if (cty.isBool())1880 if (cty.isBool())
1881 signAbbrev(.unsigned)1881 signAbbrev(.unsigned)
1882 else if (cty.isInteger())1882 else if (cty.isInteger())
1883 signAbbrev(cty.signedness() orelse .unsigned)1883 signAbbrev(cty.signedness(dg.module.getTarget()))
1884 else if (cty.isFloat())1884 else if (cty.isFloat())
1885 @as(u8, 'f')1885 @as(u8, 'f')
1886 else if (cty.isPointer())1886 else if (cty.isPointer())
src/codegen/c/type.zig+2-2
...@@ -537,9 +537,9 @@ pub const CType = extern union {...@@ -537,9 +537,9 @@ pub const CType = extern union {
537 };537 };
538 }538 }
539539
540 pub fn signedness(self: CType) ?std.builtin.Signedness {540 pub fn signedness(self: CType, target: std.Target) std.builtin.Signedness {
541 return switch (self.tag()) {541 return switch (self.tag()) {
542 .char => null, // unknown signedness542 .char => target.charSignedness(),
543 .@"signed char",543 .@"signed char",
544 .short,544 .short,
545 .int,545 .int,
src/type.zig+4-2
...@@ -2216,7 +2216,8 @@ pub const Type = struct {...@@ -2216,7 +2216,8 @@ pub const Type = struct {
2216 /// Returns true if and only if the type is a fixed-width, signed integer.2216 /// Returns true if and only if the type is a fixed-width, signed integer.
2217 pub fn isSignedInt(ty: Type, mod: *const Module) bool {2217 pub fn isSignedInt(ty: Type, mod: *const Module) bool {
2218 return switch (ty.toIntern()) {2218 return switch (ty.toIntern()) {
2219 .c_char_type, .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,2219 .c_char_type => mod.getTarget().charSignedness() == .signed,
2220 .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,
2220 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {2221 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2221 .int_type => |int_type| int_type.signedness == .signed,2222 .int_type => |int_type| int_type.signedness == .signed,
2222 else => false,2223 else => false,
...@@ -2227,6 +2228,7 @@ pub const Type = struct {...@@ -2227,6 +2228,7 @@ pub const Type = struct {
2227 /// Returns true if and only if the type is a fixed-width, unsigned integer.2228 /// Returns true if and only if the type is a fixed-width, unsigned integer.
2228 pub fn isUnsignedInt(ty: Type, mod: *const Module) bool {2229 pub fn isUnsignedInt(ty: Type, mod: *const Module) bool {
2229 return switch (ty.toIntern()) {2230 return switch (ty.toIntern()) {
2231 .c_char_type => mod.getTarget().charSignedness() == .unsigned,
2230 .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true,2232 .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true,
2231 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {2233 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2232 .int_type => |int_type| int_type.signedness == .unsigned,2234 .int_type => |int_type| int_type.signedness == .unsigned,
...@@ -2257,7 +2259,7 @@ pub const Type = struct {...@@ -2257,7 +2259,7 @@ pub const Type = struct {
2257 },2259 },
2258 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },2260 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
2259 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },2261 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
2260 .c_char_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.char) },2262 .c_char_type => return .{ .signedness = mod.getTarget().charSignedness(), .bits = target.c_type_bit_size(.char) },
2261 .c_short_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.short) },2263 .c_short_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.short) },
2262 .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ushort) },2264 .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ushort) },
2263 .c_int_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.int) },2265 .c_int_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.int) },
test/behavior.zig+1
...@@ -145,6 +145,7 @@ test {...@@ -145,6 +145,7 @@ test {
145 _ = @import("behavior/bugs/15778.zig");145 _ = @import("behavior/bugs/15778.zig");
146 _ = @import("behavior/byteswap.zig");146 _ = @import("behavior/byteswap.zig");
147 _ = @import("behavior/byval_arg_var.zig");147 _ = @import("behavior/byval_arg_var.zig");
148 _ = @import("behavior/c_char_signedness.zig");
148 _ = @import("behavior/call.zig");149 _ = @import("behavior/call.zig");
149 _ = @import("behavior/cast.zig");150 _ = @import("behavior/cast.zig");
150 _ = @import("behavior/cast_int.zig");151 _ = @import("behavior/cast_int.zig");
test/behavior/c_char_signedness.zig created+10
...@@ -0,0 +1,10 @@
1const std = @import("std");
2const expectEqual = std.testing.expectEqual;
3const c = @cImport({
4 @cInclude("limits.h");
5});
6
7test "c_char signedness" {
8 try expectEqual(@as(c_char, c.CHAR_MIN), std.math.minInt(c_char));
9 try expectEqual(@as(c_char, c.CHAR_MAX), std.math.maxInt(c_char));
10}