From 874ae81f1b2ae76cea6f5c79203f4baa68263163 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 3 Mar 2023 00:18:34 -0500 Subject: CBE: implement big integer literals --- src/codegen/c/type.zig | 348 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 317 insertions(+), 31 deletions(-) (limited to 'src/codegen/c/type.zig') diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 1f1a220cd2..a1b11df315 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -496,6 +496,296 @@ pub const CType = extern union { } }; + pub fn toSigned(self: CType) CType { + return CType.initTag(switch (self.tag()) { + .char, .@"signed char", .@"unsigned char" => .@"signed char", + .short, .@"unsigned short" => .short, + .int, .@"unsigned int" => .int, + .long, .@"unsigned long" => .long, + .@"long long", .@"unsigned long long" => .@"long long", + .size_t, .ptrdiff_t => .ptrdiff_t, + .uint8_t, .int8_t => .int8_t, + .uint16_t, .int16_t => .int16_t, + .uint32_t, .int32_t => .int32_t, + .uint64_t, .int64_t => .int64_t, + .uintptr_t, .intptr_t => .intptr_t, + .zig_u128, .zig_i128 => .zig_i128, + .float, + .double, + .@"long double", + .zig_f16, + .zig_f32, + .zig_f80, + .zig_f128, + .zig_c_longdouble, + => |t| t, + else => unreachable, + }); + } + + pub fn toUnsigned(self: CType) CType { + return CType.initTag(switch (self.tag()) { + .char, .@"signed char", .@"unsigned char" => .@"unsigned char", + .short, .@"unsigned short" => .@"unsigned short", + .int, .@"unsigned int" => .@"unsigned int", + .long, .@"unsigned long" => .@"unsigned long", + .@"long long", .@"unsigned long long" => .@"unsigned long long", + .size_t, .ptrdiff_t => .size_t, + .uint8_t, .int8_t => .uint8_t, + .uint16_t, .int16_t => .uint16_t, + .uint32_t, .int32_t => .uint32_t, + .uint64_t, .int64_t => .uint64_t, + .uintptr_t, .intptr_t => .uintptr_t, + .zig_u128, .zig_i128 => .zig_u128, + else => unreachable, + }); + } + + pub fn getStandardDefineAbbrev(self: CType) ?[]const u8 { + return switch (self.tag()) { + .char => "CHAR", + .@"signed char" => "SCHAR", + .short => "SHRT", + .int => "INT", + .long => "LONG", + .@"long long" => "LLONG", + .@"unsigned char" => "UCHAR", + .@"unsigned short" => "USHRT", + .@"unsigned int" => "UINT", + .@"unsigned long" => "ULONG", + .@"unsigned long long" => "ULLONG", + .float => "FLT", + .double => "DBL", + .@"long double" => "LDBL", + .size_t => "SIZE", + .ptrdiff_t => "PTRDIFF", + .uint8_t => "UINT8", + .int8_t => "INT8", + .uint16_t => "UINT16", + .int16_t => "INT16", + .uint32_t => "UINT32", + .int32_t => "INT32", + .uint64_t => "UINT64", + .int64_t => "INT64", + .uintptr_t => "UINTPTR", + .intptr_t => "INTPTR", + else => null, + }; + } + + pub fn renderLiteralPrefix(self: CType, writer: anytype, kind: Kind) @TypeOf(writer).Error!void { + switch (self.tag()) { + .void => unreachable, + ._Bool, + .char, + .@"signed char", + .short, + .@"unsigned short", + .bool, + .size_t, + .ptrdiff_t, + .uintptr_t, + .intptr_t, + => |t| switch (kind) { + else => try writer.print("({s})", .{@tagName(t)}), + .global => {}, + }, + .int, + .long, + .@"long long", + .@"unsigned char", + .@"unsigned int", + .@"unsigned long", + .@"unsigned long long", + .float, + .double, + .@"long double", + => {}, + .uint8_t, + .int8_t, + .uint16_t, + .int16_t, + .uint32_t, + .int32_t, + .uint64_t, + .int64_t, + => try writer.print("{s}_C(", .{self.getStandardDefineAbbrev().?}), + .zig_u128, + .zig_i128, + .zig_f16, + .zig_f32, + .zig_f64, + .zig_f80, + .zig_f128, + .zig_c_longdouble, + => |t| try writer.print("zig_{s}_{s}(", .{ + switch (kind) { + else => "make", + .global => "init", + }, + @tagName(t)["zig_".len..], + }), + .pointer, + .pointer_const, + .pointer_volatile, + .pointer_const_volatile, + => unreachable, + .array, + .vector, + => try writer.writeByte('{'), + .fwd_anon_struct, + .fwd_anon_union, + .fwd_struct, + .fwd_union, + .unnamed_struct, + .unnamed_union, + .packed_unnamed_struct, + .packed_unnamed_union, + .anon_struct, + .anon_union, + .@"struct", + .@"union", + .packed_struct, + .packed_union, + .function, + .varargs_function, + => unreachable, + } + } + + pub fn renderLiteralSuffix(self: CType, writer: anytype) @TypeOf(writer).Error!void { + switch (self.tag()) { + .void => unreachable, + ._Bool => {}, + .char, + .@"signed char", + .short, + .int, + => {}, + .long => try writer.writeByte('l'), + .@"long long" => try writer.writeAll("ll"), + .@"unsigned char", + .@"unsigned short", + .@"unsigned int", + => try writer.writeByte('u'), + .@"unsigned long", + .size_t, + .uintptr_t, + => try writer.writeAll("ul"), + .@"unsigned long long" => try writer.writeAll("ull"), + .float => try writer.writeByte('f'), + .double => {}, + .@"long double" => try writer.writeByte('l'), + .bool, + .ptrdiff_t, + .intptr_t, + => {}, + .uint8_t, + .int8_t, + .uint16_t, + .int16_t, + .uint32_t, + .int32_t, + .uint64_t, + .int64_t, + .zig_u128, + .zig_i128, + .zig_f16, + .zig_f32, + .zig_f64, + .zig_f80, + .zig_f128, + .zig_c_longdouble, + => try writer.writeByte(')'), + .pointer, + .pointer_const, + .pointer_volatile, + .pointer_const_volatile, + => unreachable, + .array, + .vector, + => try writer.writeByte('}'), + .fwd_anon_struct, + .fwd_anon_union, + .fwd_struct, + .fwd_union, + .unnamed_struct, + .unnamed_union, + .packed_unnamed_struct, + .packed_unnamed_union, + .anon_struct, + .anon_union, + .@"struct", + .@"union", + .packed_struct, + .packed_union, + .function, + .varargs_function, + => unreachable, + } + } + + pub fn byteSize(self: CType, store: Store.Set, target: Target) u64 { + return switch (self.tag()) { + .void => 0, + .char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1, + .short => target.c_type_byte_size(.short), + .int => target.c_type_byte_size(.int), + .long => target.c_type_byte_size(.long), + .@"long long" => target.c_type_byte_size(.longlong), + .@"unsigned short" => target.c_type_byte_size(.ushort), + .@"unsigned int" => target.c_type_byte_size(.uint), + .@"unsigned long" => target.c_type_byte_size(.ulong), + .@"unsigned long long" => target.c_type_byte_size(.ulonglong), + .float => target.c_type_byte_size(.float), + .double => target.c_type_byte_size(.double), + .@"long double" => target.c_type_byte_size(.longdouble), + .size_t, + .ptrdiff_t, + .uintptr_t, + .intptr_t, + .pointer, + .pointer_const, + .pointer_volatile, + .pointer_const_volatile, + => @divExact(target.cpu.arch.ptrBitWidth(), 8), + .uint16_t, .int16_t, .zig_f16 => 2, + .uint32_t, .int32_t, .zig_f32 => 4, + .uint64_t, .int64_t, .zig_f64 => 8, + .zig_u128, .zig_i128, .zig_f128 => 16, + .zig_f80 => if (target.c_type_bit_size(.longdouble) == 80) + target.c_type_byte_size(.longdouble) + else + 16, + .zig_c_longdouble => target.c_type_byte_size(.longdouble), + + .array, + .vector, + => { + const data = self.cast(Payload.Sequence).?.data; + return data.len * store.indexToCType(data.elem_type).byteSize(store, target); + }, + + .fwd_anon_struct, + .fwd_anon_union, + .fwd_struct, + .fwd_union, + .unnamed_struct, + .unnamed_union, + .packed_unnamed_struct, + .packed_unnamed_union, + .anon_struct, + .anon_union, + .@"struct", + .@"union", + .packed_struct, + .packed_union, + .function, + .varargs_function, + => unreachable, + }; + } + pub fn isPacked(self: CType) bool { return switch (self.tag()) { else => false, @@ -787,26 +1077,26 @@ pub const CType = extern union { }; } - fn tagFromIntInfo(signedness: std.builtin.Signedness, bits: u16) Tag { - return switch (bits) { + fn tagFromIntInfo(int_info: std.builtin.Type.Int) Tag { + return switch (int_info.bits) { 0 => .void, - 1...8 => switch (signedness) { + 1...8 => switch (int_info.signedness) { .unsigned => .uint8_t, .signed => .int8_t, }, - 9...16 => switch (signedness) { + 9...16 => switch (int_info.signedness) { .unsigned => .uint16_t, .signed => .int16_t, }, - 17...32 => switch (signedness) { + 17...32 => switch (int_info.signedness) { .unsigned => .uint32_t, .signed => .int32_t, }, - 33...64 => switch (signedness) { + 33...64 => switch (int_info.signedness) { .unsigned => .uint64_t, .signed => .int64_t, }, - 65...128 => switch (signedness) { + 65...128 => switch (int_info.signedness) { .unsigned => .zig_u128, .signed => .zig_i128, }, @@ -945,31 +1235,27 @@ pub const CType = extern union { .c_ulong => self.init(.@"unsigned long"), .c_longlong => self.init(.@"long long"), .c_ulonglong => self.init(.@"unsigned long long"), - else => { - const info = ty.intInfo(target); - const t = tagFromIntInfo(info.signedness, info.bits); - switch (t) { - .void => unreachable, - else => self.init(t), - .array => switch (kind) { - .forward, .complete, .global => { - const abi_size = ty.abiSize(target); - const abi_align = ty.abiAlignment(target); - self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{ - .len = @divExact(abi_size, abi_align), - .elem_type = tagFromIntInfo( - .unsigned, - @intCast(u16, abi_align * 8), - ).toIndex(), - } } }; - self.value = .{ .cty = initPayload(&self.storage.seq) }; - }, - .forward_parameter, - .parameter, - => try self.initArrayParameter(ty, kind, lookup), - .payload => unreachable, + else => switch (tagFromIntInfo(ty.intInfo(target))) { + .void => unreachable, + else => |t| self.init(t), + .array => switch (kind) { + .forward, .complete, .global => { + const abi_size = ty.abiSize(target); + const abi_align = ty.abiAlignment(target); + self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{ + .len = @divExact(abi_size, abi_align), + .elem_type = tagFromIntInfo(.{ + .signedness = .unsigned, + .bits = @intCast(u16, abi_align * 8), + }).toIndex(), + } } }; + self.value = .{ .cty = initPayload(&self.storage.seq) }; }, - } + .forward_parameter, + .parameter, + => try self.initArrayParameter(ty, kind, lookup), + .payload => unreachable, + }, }, } else switch (ty.zigTypeTag()) { .Frame => unreachable, -- cgit v1.2.3 From a8f4ac2b94e7945a5a1623547f258f5f32f12674 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 3 Mar 2023 00:18:35 -0500 Subject: CBE: implement big integer and vector comparisons --- lib/zig.h | 313 ++++++++++++++++++++++++++++++++++-------- src/codegen/c.zig | 342 +++++++++++++++++++++++++++++----------------- src/codegen/c/type.zig | 124 +++++++++++++++++ src/type.zig | 2 +- test/behavior/bitcast.zig | 2 - test/behavior/math.zig | 1 - test/behavior/vector.zig | 2 - 7 files changed, 595 insertions(+), 191 deletions(-) (limited to 'src/codegen/c/type.zig') diff --git a/lib/zig.h b/lib/zig.h index 7353ea935d..c39cffee24 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -37,6 +37,14 @@ typedef char bool; #define zig_has_attribute(attribute) 0 #endif +#if __LITTLE_ENDIAN__ || _MSC_VER +#define zig_little_endian 1 +#define zig_big_endian 0 +#else +#define zig_little_endian 0 +#define zig_big_endian 1 +#endif + #if __STDC_VERSION__ >= 201112L #define zig_threadlocal _Thread_local #elif defined(__GNUC__) @@ -1379,7 +1387,7 @@ typedef signed __int128 zig_i128; #else /* zig_has_int128 */ -#if __LITTLE_ENDIAN__ || _MSC_VER +#if zig_little_endian typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128; typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128; #else @@ -1909,6 +1917,177 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { return zig_bitcast_i128(zig_bit_reverse_u128(zig_bitcast_u128(val), bits)); } +/* ========================== Big Integer Support =========================== */ + +static inline uint16_t zig_big_bytes(uint16_t bits) { + uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT; + uint16_t alignment = 16; + while (alignment / 2 >= bytes) alignment /= 2; + return (bytes + alignment - 1) / alignment * alignment; +} + +static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + const uint8_t *lhs_bytes = lhs; + const uint8_t *rhs_bytes = rhs; + uint16_t byte_offset = 0; + bool do_signed = is_signed; + uint16_t remaining_bytes = zig_big_bytes(bits); + +#if zig_little_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + int32_t limb_cmp; + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (do_signed) { + zig_i128 lhs_limb; + zig_i128 rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb); + do_signed = false; + } else { + zig_u128 lhs_limb; + zig_u128 rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb); + } + + if (limb_cmp != 0) return limb_cmp; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (do_signed) { + int64_t lhs_limb; + int64_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint64_t lhs_limb; + uint64_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (do_signed) { + int32_t lhs_limb; + int32_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint32_t lhs_limb; + uint32_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (do_signed) { + int16_t lhs_limb; + int16_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint16_t lhs_limb; + uint16_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (do_signed) { + int8_t lhs_limb; + int8_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint8_t lhs_limb; + uint8_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + } + + return 0; +} + /* ========================= Floating Point Support ========================= */ #if _MSC_VER @@ -1933,7 +2112,6 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { #define zig_make_special_f64(sign, name, arg, repr) sign zig_make_f64(__builtin_##name, )(arg) #define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80(__builtin_##name, )(arg) #define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg) -#define zig_make_special_c_longdouble(sign, name, arg, repr) sign zig_make_c_longdouble(__builtin_##name, )(arg) #else #define zig_has_float_builtins 0 #define zig_make_special_f16(sign, name, arg, repr) zig_float_from_repr_f16(repr) @@ -1941,13 +2119,13 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { #define zig_make_special_f64(sign, name, arg, repr) zig_float_from_repr_f64(repr) #define zig_make_special_f80(sign, name, arg, repr) zig_float_from_repr_f80(repr) #define zig_make_special_f128(sign, name, arg, repr) zig_float_from_repr_f128(repr) -#define zig_make_special_c_longdouble(sign, name, arg, repr) zig_float_from_repr_c_longdouble(repr) #endif #define zig_has_f16 1 #define zig_bitSizeOf_f16 16 +typedef int16_t zig_repr_f16; #define zig_libc_name_f16(name) __##name##h -#define zig_make_special_constant_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr) +#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr) #if FLT_MANT_DIG == 11 typedef float zig_f16; #define zig_make_f16(fp, repr) fp##f @@ -1956,7 +2134,9 @@ typedef double zig_f16; #define zig_make_f16(fp, repr) fp #elif LDBL_MANT_DIG == 11 #define zig_bitSizeOf_c_longdouble 16 -typedef uint16_t zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f16 zig_repr_c_longdouble; +#endif typedef long double zig_f16; #define zig_make_f16(fp, repr) fp##l #elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gnuc)) @@ -1973,17 +2153,18 @@ typedef int16_t zig_f16; #define zig_make_f16(fp, repr) repr #undef zig_make_special_f16 #define zig_make_special_f16(sign, name, arg, repr) repr -#undef zig_make_special_constant_f16 -#define zig_make_special_constant_f16(sign, name, arg, repr) repr +#undef zig_init_special_f16 +#define zig_init_special_f16(sign, name, arg, repr) repr #endif #define zig_has_f32 1 #define zig_bitSizeOf_f32 32 +typedef int32_t zig_repr_f32; #define zig_libc_name_f32(name) name##f #if _MSC_VER -#define zig_make_special_constant_f32(sign, name, arg, repr) sign zig_make_f32(zig_msvc_flt_##name, ) +#define zig_init_special_f32(sign, name, arg, repr) sign zig_make_f32(zig_msvc_flt_##name, ) #else -#define zig_make_special_constant_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr) +#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr) #endif #if FLT_MANT_DIG == 24 typedef float zig_f32; @@ -1993,7 +2174,9 @@ typedef double zig_f32; #define zig_make_f32(fp, repr) fp #elif LDBL_MANT_DIG == 24 #define zig_bitSizeOf_c_longdouble 32 -typedef uint32_t zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f32 zig_repr_c_longdouble; +#endif typedef long double zig_f32; #define zig_make_f32(fp, repr) fp##l #elif FLT32_MANT_DIG == 24 @@ -2007,21 +2190,24 @@ typedef int32_t zig_f32; #define zig_make_f32(fp, repr) repr #undef zig_make_special_f32 #define zig_make_special_f32(sign, name, arg, repr) repr -#undef zig_make_special_constant_f32 -#define zig_make_special_constant_f32(sign, name, arg, repr) repr +#undef zig_init_special_f32 +#define zig_init_special_f32(sign, name, arg, repr) repr #endif #define zig_has_f64 1 #define zig_bitSizeOf_f64 64 +typedef int64_t zig_repr_f64; #define zig_libc_name_f64(name) name #if _MSC_VER #ifdef ZIG_TARGET_ABI_MSVC #define zig_bitSizeOf_c_longdouble 64 -typedef uint64_t zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f64 zig_repr_c_longdouble; +#endif #endif -#define zig_make_special_constant_f64(sign, name, arg, repr) sign zig_make_f64(zig_msvc_flt_##name, ) +#define zig_init_special_f64(sign, name, arg, repr) sign zig_make_f64(zig_msvc_flt_##name, ) #else /* _MSC_VER */ -#define zig_make_special_constant_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr) +#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr) #endif /* _MSC_VER */ #if FLT_MANT_DIG == 53 typedef float zig_f64; @@ -2031,7 +2217,9 @@ typedef double zig_f64; #define zig_make_f64(fp, repr) fp #elif LDBL_MANT_DIG == 53 #define zig_bitSizeOf_c_longdouble 64 -typedef uint64_t zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f64 zig_repr_c_longdouble; +#endif typedef long double zig_f64; #define zig_make_f64(fp, repr) fp##l #elif FLT64_MANT_DIG == 53 @@ -2048,14 +2236,15 @@ typedef int64_t zig_f64; #define zig_make_f64(fp, repr) repr #undef zig_make_special_f64 #define zig_make_special_f64(sign, name, arg, repr) repr -#undef zig_make_special_constant_f64 -#define zig_make_special_constant_f64(sign, name, arg, repr) repr +#undef zig_init_special_f64 +#define zig_init_special_f64(sign, name, arg, repr) repr #endif #define zig_has_f80 1 #define zig_bitSizeOf_f80 80 +typedef zig_i128 zig_repr_f80; #define zig_libc_name_f80(name) __##name##x -#define zig_make_special_constant_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr) +#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr) #if FLT_MANT_DIG == 64 typedef float zig_f80; #define zig_make_f80(fp, repr) fp##f @@ -2064,7 +2253,9 @@ typedef double zig_f80; #define zig_make_f80(fp, repr) fp #elif LDBL_MANT_DIG == 64 #define zig_bitSizeOf_c_longdouble 80 -typedef zig_u128 zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f80 zig_repr_c_longdouble; +#endif typedef long double zig_f80; #define zig_make_f80(fp, repr) fp##l #elif FLT80_MANT_DIG == 64 @@ -2084,14 +2275,15 @@ typedef zig_i128 zig_f80; #define zig_make_f80(fp, repr) repr #undef zig_make_special_f80 #define zig_make_special_f80(sign, name, arg, repr) repr -#undef zig_make_special_constant_f80 -#define zig_make_special_constant_f80(sign, name, arg, repr) repr +#undef zig_init_special_f80 +#define zig_init_special_f80(sign, name, arg, repr) repr #endif #define zig_has_f128 1 #define zig_bitSizeOf_f128 128 +typedef zig_i128 zig_repr_f128; #define zig_libc_name_f128(name) name##q -#define zig_make_special_constant_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) +#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) #if FLT_MANT_DIG == 113 typedef float zig_f128; #define zig_make_f128(fp, repr) fp##f @@ -2100,7 +2292,9 @@ typedef double zig_f128; #define zig_make_f128(fp, repr) fp #elif LDBL_MANT_DIG == 113 #define zig_bitSizeOf_c_longdouble 128 -typedef zig_u128 zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f128 zig_repr_c_longdouble; +#endif typedef long double zig_f128; #define zig_make_f128(fp, repr) fp##l #elif FLT128_MANT_DIG == 113 @@ -2122,63 +2316,44 @@ typedef zig_i128 zig_f128; #define zig_make_f128(fp, repr) repr #undef zig_make_special_f128 #define zig_make_special_f128(sign, name, arg, repr) repr -#undef zig_make_special_constant_f128 -#define zig_make_special_constant_f128(sign, name, arg, repr) repr +#undef zig_init_special_f128 +#define zig_init_special_f128(sign, name, arg, repr) repr #endif -#define zig_has_c_longdouble 1 - -#ifdef ZIG_TARGET_ABI_MSVC -#define zig_libc_name_c_longdouble(name) name -#else -#define zig_libc_name_c_longdouble(name) name##l -#endif - -#define zig_make_special_constant_c_longdouble(sign, name, arg, repr) zig_make_special_c_longdouble(sign, name, arg, repr) #ifdef zig_bitSizeOf_c_longdouble +#define zig_has_c_longdouble 1 #ifdef ZIG_TARGET_ABI_MSVC #undef zig_bitSizeOf_c_longdouble #define zig_bitSizeOf_c_longdouble 64 -typedef uint64_t zig_repr_c_longdouble; typedef zig_f64 zig_c_longdouble; -#define zig_make_c_longdouble(fp, repr) fp +typedef zig_repr_f64 zig_repr_c_longdouble; #else typedef long double zig_c_longdouble; -#define zig_make_c_longdouble(fp, repr) fp##l #endif #else /* zig_bitSizeOf_c_longdouble */ -#undef zig_has_c_longdouble #define zig_has_c_longdouble 0 -#define zig_bitSizeOf_c_longdouble 80 -typedef zig_u128 zig_repr_c_longdouble; -#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f80 #define zig_bitSizeOf_repr_c_longdouble 128 -typedef zig_i128 zig_c_longdouble; -#define zig_make_c_longdouble(fp, repr) repr -#undef zig_make_special_c_longdouble -#define zig_make_special_c_longdouble(sign, name, arg, repr) repr -#undef zig_make_special_constant_c_longdouble -#define zig_make_special_constant_c_longdouble(sign, name, arg, repr) repr +typedef zig_f128 zig_c_longdouble; +typedef zig_repr_f128 zig_repr_c_longdouble; #endif /* zig_bitSizeOf_c_longdouble */ #if !zig_has_float_builtins -#define zig_float_from_repr(Type, ReprType) \ - static inline zig_##Type zig_float_from_repr_##Type(ReprType repr) { \ +#define zig_float_from_repr(Type) \ + static inline zig_##Type zig_float_from_repr_##Type(zig_repr_##Type repr) { \ zig_##Type result; \ memcpy(&result, &repr, sizeof(result)); \ return result; \ } -zig_float_from_repr(f16, uint16_t) -zig_float_from_repr(f32, uint32_t) -zig_float_from_repr(f64, uint64_t) -zig_float_from_repr(f80, zig_u128) -zig_float_from_repr(f128, zig_u128) -zig_float_from_repr(c_longdouble, zig_repr_c_longdouble) +zig_float_from_repr(f16) +zig_float_from_repr(f32) +zig_float_from_repr(f64) +zig_float_from_repr(f80) +zig_float_from_repr(f128) #endif #define zig_cast_f16 (zig_f16) @@ -2187,11 +2362,9 @@ zig_float_from_repr(c_longdouble, zig_repr_c_longdouble) #if _MSC_VER && !zig_has_f128 #define zig_cast_f80 -#define zig_cast_c_longdouble #define zig_cast_f128 #else #define zig_cast_f80 (zig_f80) -#define zig_cast_c_longdouble (zig_c_longdouble) #define zig_cast_f128 (zig_f128) #endif @@ -2320,7 +2493,6 @@ zig_float_builtins(f32) zig_float_builtins(f64) zig_float_builtins(f80) zig_float_builtins(f128) -zig_float_builtins(c_longdouble) #if _MSC_VER && (_M_IX86 || _M_X64) @@ -2563,6 +2735,29 @@ zig_msvc_atomics_128op(u128, max) #endif /* _MSC_VER && (_M_IX86 || _M_X64) */ +/* ============================= Vector Support ============================= */ + +#define zig_cmp_vec(operation, operator) \ + static inline void zig_##operation##_vec(bool *result, const void *lhs, const void *rhs, uint32_t len, bool is_signed, uint16_t elem_bits) { \ + uint32_t index = 0; \ + const uint8_t *lhs_ptr = lhs; \ + const uint8_t *rhs_ptr = rhs; \ + uint16_t elem_bytes = zig_big_bytes(elem_bits); \ + \ + while (index < len) { \ + result[index] = zig_cmp_big(lhs_ptr, rhs_ptr, is_signed, elem_bits) operator 0; \ + lhs_ptr += elem_bytes; \ + rhs_ptr += elem_bytes; \ + index += 1; \ + } \ + } +zig_cmp_vec(eq, ==) +zig_cmp_vec(ne, !=) +zig_cmp_vec(lt, < ) +zig_cmp_vec(le, <=) +zig_cmp_vec(gt, > ) +zig_cmp_vec(ge, >=) + /* ======================== Special Case Intrinsics ========================= */ #if (_MSC_VER && _M_X64) || defined(__x86_64__) diff --git a/src/codegen/c.zig b/src/codegen/c.zig index addd3c8332..f4a817cecd 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -112,11 +112,7 @@ const ValueRenderLocation = enum { } }; -const BuiltinInfo = enum { - None, - Range, - Bits, -}; +const BuiltinInfo = enum { none, bits }; const reserved_idents = std.ComptimeStringMap(void, .{ // C language @@ -440,6 +436,10 @@ pub const Function = struct { return f.object.dg.typeToCType(ty, kind); } + fn byteSize(f: *Function, cty: CType) u64 { + return f.object.dg.byteSize(cty); + } + fn renderType(f: *Function, w: anytype, t: Type) !void { return f.object.dg.renderType(w, t); } @@ -1003,8 +1003,9 @@ pub const DeclGen = struct { // return dg.fail("Only quiet nans are supported in global variable initializers", .{}); } - try writer.writeAll("zig_make_special_"); - if (location == .StaticInitializer) try writer.writeAll("constant_"); + try writer.writeAll("zig_"); + try writer.writeAll(if (location == .StaticInitializer) "init" else "make"); + try writer.writeAll("_special_"); try dg.renderTypeForBuiltinFnName(writer, ty); try writer.writeByte('('); if (std.math.signbit(f128_val)) try writer.writeByte('-'); @@ -1565,6 +1566,10 @@ pub const DeclGen = struct { return dg.ctypes.typeToCType(dg.gpa, ty, dg.module, kind); } + fn byteSize(dg: *DeclGen, cty: CType) u64 { + return cty.byteSize(dg.ctypes.set, dg.module.getTarget()); + } + /// Renders a type as a single identifier, generating intermediate typedefs /// if necessary. /// @@ -1861,51 +1866,64 @@ pub const DeclGen = struct { } fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void { - const target = dg.module.getTarget(); - if (ty.isAbiInt()) { - const int_info = ty.intInfo(target); - const c_bits = toCIntBits(int_info.bits) orelse - return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); - try writer.print("{c}{d}", .{ signAbbrev(int_info.signedness), c_bits }); - } else if (ty.isRuntimeFloat()) { - try ty.print(writer, dg.module); - } else if (ty.isPtrAtRuntime()) { - try writer.print("p{d}", .{ty.bitSize(target)}); - } else if (ty.zigTypeTag() == .Bool) { - try writer.print("u8", .{}); - } else return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{ - ty.fmt(dg.module), - }); + try dg.renderCTypeForBuiltinFnName(writer, try dg.typeToCType(ty, .complete)); + } + + fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, cty: CType) !void { + switch (cty.tag()) { + else => try writer.print("{c}{d}", .{ + if (cty.isBool()) + signAbbrev(.unsigned) + else if (cty.isInteger()) + signAbbrev(cty.signedness() orelse .unsigned) + else if (cty.isFloat()) + @as(u8, 'f') + else if (cty.isPointer()) + @as(u8, 'p') + else + return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{ + cty.tag(), + }), + if (cty.isFloat()) cty.floatActiveBits(dg.module.getTarget()) else dg.byteSize(cty) * 8, + }), + .array => try writer.writeAll("big"), + .vector => try writer.writeAll("vec"), + } } fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void { - const target = dg.module.getTarget(); switch (info) { - .None => {}, - .Range => { - var arena = std.heap.ArenaAllocator.init(dg.gpa); - defer arena.deinit(); - - const ExpectedContents = union { u: Value.Payload.U64, i: Value.Payload.I64 }; - var stack align(@alignOf(ExpectedContents)) = - std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator()); - - const int_info = ty.intInfo(target); - if (int_info.signedness == .signed) { - const min_val = try ty.minInt(stack.get(), target); - try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, min_val, .Other)}); + .none => {}, + .bits => { + const cty = try dg.typeToCType(ty, .complete); + if (cty.castTag(.vector)) |pl| { + var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = pl.data.len }; + try writer.print(", {}", .{try dg.fmtIntLiteral( + Type.u32, + Value.initPayload(&len_pl.base), + .FunctionArgument, + )}); } - const max_val = try ty.maxInt(stack.get(), target); - try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, max_val, .Other)}); - }, - .Bits => { - var bits_pl = Value.Payload.U64{ - .base = .{ .tag = .int_u64 }, - .data = ty.bitSize(target), - }; - const bits_val = Value.initPayload(&bits_pl.base); - try writer.print(", {}", .{try dg.fmtIntLiteral(Type.u8, bits_val, .Other)}); + const target = dg.module.getTarget(); + const elem_ty = ty.shallowElemType(); + const elem_info = if (elem_ty.isAbiInt()) + elem_ty.intInfo(target) + else + std.builtin.Type.Int{ + .signedness = .unsigned, + .bits = @intCast(u16, elem_ty.bitSize(target)), + }; + switch (cty.tag()) { + else => {}, + .array, .vector => try writer.print(", {}", .{elem_info.signedness == .signed}), + } + + var bits_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = elem_info.bits }; + try writer.print(", {}", .{try dg.fmtIntLiteral(switch (cty.tag()) { + else => Type.u8, + .array, .vector => Type.u16, + }, Value.initPayload(&bits_pl.base), .FunctionArgument)}); }, } } @@ -2758,35 +2776,35 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, // TODO use a different strategy for add, sub, mul, div // that communicates to the optimizer that wrapping is UB. - .add => try airBinOp(f, inst, "+", "add", .None), - .sub => try airBinOp(f, inst, "-", "sub", .None), - .mul => try airBinOp(f, inst, "*", "mul", .None), + .add => try airBinOp(f, inst, "+", "add", .none), + .sub => try airBinOp(f, inst, "-", "sub", .none), + .mul => try airBinOp(f, inst, "*", "mul", .none), .neg => try airFloatNeg(f, inst), - .div_float => try airBinBuiltinCall(f, inst, "div", .None), + .div_float => try airBinBuiltinCall(f, inst, "div", .none), - .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None), + .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none), .rem => blk: { const bin_op = f.air.instructions.items(.data)[inst].bin_op; const lhs_ty = f.air.typeOf(bin_op.lhs); // For binary operations @TypeOf(lhs)==@TypeOf(rhs), // so we only check one. break :blk if (lhs_ty.isInt()) - try airBinOp(f, inst, "%", "rem", .None) + try airBinOp(f, inst, "%", "rem", .none) else try airBinFloatOp(f, inst, "fmod"); }, - .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None), - .mod => try airBinBuiltinCall(f, inst, "mod", .None), + .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none), + .mod => try airBinBuiltinCall(f, inst, "mod", .none), - .addwrap => try airBinBuiltinCall(f, inst, "addw", .Bits), - .subwrap => try airBinBuiltinCall(f, inst, "subw", .Bits), - .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .Bits), + .addwrap => try airBinBuiltinCall(f, inst, "addw", .bits), + .subwrap => try airBinBuiltinCall(f, inst, "subw", .bits), + .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .bits), - .add_sat => try airBinBuiltinCall(f, inst, "adds", .Bits), - .sub_sat => try airBinBuiltinCall(f, inst, "subs", .Bits), - .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits), - .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits), + .add_sat => try airBinBuiltinCall(f, inst, "adds", .bits), + .sub_sat => try airBinBuiltinCall(f, inst, "subs", .bits), + .mul_sat => try airBinBuiltinCall(f, inst, "muls", .bits), + .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits), .sqrt => try airUnFloatOp(f, inst, "sqrt"), .sin => try airUnFloatOp(f, inst, "sin"), @@ -2805,34 +2823,38 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, .mul_add => try airMulAdd(f, inst), - .add_with_overflow => try airOverflow(f, inst, "add", .Bits), - .sub_with_overflow => try airOverflow(f, inst, "sub", .Bits), - .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits), - .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits), + .add_with_overflow => try airOverflow(f, inst, "add", .bits), + .sub_with_overflow => try airOverflow(f, inst, "sub", .bits), + .mul_with_overflow => try airOverflow(f, inst, "mul", .bits), + .shl_with_overflow => try airOverflow(f, inst, "shl", .bits), .min => try airMinMax(f, inst, '<', "fmin"), .max => try airMinMax(f, inst, '>', "fmax"), .slice => try airSlice(f, inst), - .cmp_gt => try airCmpOp(f, inst, ">", "gt"), - .cmp_gte => try airCmpOp(f, inst, ">=", "ge"), - .cmp_lt => try airCmpOp(f, inst, "<", "lt"), - .cmp_lte => try airCmpOp(f, inst, "<=", "le"), + .cmp_gt => try airCmpOp(f, inst, .gt), + .cmp_gte => try airCmpOp(f, inst, .gte), + .cmp_lt => try airCmpOp(f, inst, .lt), + .cmp_lte => try airCmpOp(f, inst, .lte), - .cmp_eq => try airEquality(f, inst, "((", "==", "eq"), - .cmp_neq => try airEquality(f, inst, "!((", "!=", "ne"), + .cmp_eq => try airEquality(f, inst, .eq), + .cmp_neq => try airEquality(f, inst, .neq), - .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}), + .cmp_vector => blk: { + const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; + const extra = f.air.extraData(Air.VectorCmp, ty_pl.payload).data; + break :blk try cmpBuiltinCall(f, inst, extra, extra.compareOperator(), .operator, .bits); + }, .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst), // bool_and and bool_or are non-short-circuit operations - .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .None), - .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .None), - .xor => try airBinOp(f, inst, "^", "xor", .None), - .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .None), - .shl, => try airBinBuiltinCall(f, inst, "shlw", .Bits), - .shl_exact => try airBinOp(f, inst, "<<", "shl", .None), + .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .none), + .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .none), + .xor => try airBinOp(f, inst, "^", "xor", .none), + .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .none), + .shl, => try airBinBuiltinCall(f, inst, "shlw", .bits), + .shl_exact => try airBinOp(f, inst, "<<", "shl", .none), .not => try airNot (f, inst), .optional_payload => try airOptionalPayload(f, inst), @@ -2877,11 +2899,11 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, .memcpy => try airMemcpy(f, inst), .set_union_tag => try airSetUnionTag(f, inst), .get_union_tag => try airGetUnionTag(f, inst), - .clz => try airUnBuiltinCall(f, inst, "clz", .Bits), - .ctz => try airUnBuiltinCall(f, inst, "ctz", .Bits), - .popcount => try airUnBuiltinCall(f, inst, "popcount", .Bits), - .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .Bits), - .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .Bits), + .clz => try airUnBuiltinCall(f, inst, "clz", .bits), + .ctz => try airUnBuiltinCall(f, inst, "ctz", .bits), + .popcount => try airUnBuiltinCall(f, inst, "popcount", .bits), + .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .bits), + .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .bits), .tag_name => try airTagName(f, inst), .error_name => try airErrorName(f, inst), .splat => try airSplat(f, inst), @@ -3349,7 +3371,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValueDeref(writer, operand); try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)}); if (cant_cast) try writer.writeByte(')'); - try f.object.dg.renderBuiltinInfo(writer, field_ty, .Bits); + try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits); try writer.writeByte(')'); } else { try f.writeCValue(writer, local, .Other); @@ -3744,7 +3766,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.air.typeOfIndex(inst); if (inst_ty.tag() != .bool) - return try airUnBuiltinCall(f, inst, "not", .Bits); + return try airUnBuiltinCall(f, inst, "not", .bits); const ty_op = f.air.instructions.items(.data)[inst].ty_op; @@ -3803,7 +3825,7 @@ fn airBinOp( return local; } -fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: []const u8) !CValue { +fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: std.math.CompareOperator) !CValue { const bin_op = f.air.instructions.items(.data)[inst].bin_op; if (f.liveness.isUnused(inst)) { @@ -3813,10 +3835,11 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: const operand_ty = f.air.typeOf(bin_op.lhs); const target = f.object.dg.module.getTarget(); - if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) - return try cmpBuiltinCall(f, inst, operator, "cmp"); + const operand_bits = operand_ty.bitSize(target); + if (operand_ty.isInt() and operand_bits > 64) + return cmpBuiltinCall(f, inst, bin_op, operator, .cmp, if (operand_bits > 128) .bits else .none); if (operand_ty.isRuntimeFloat()) - return try cmpBuiltinCall(f, inst, operator, operation); + return cmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); const inst_ty = f.air.typeOfIndex(inst); const lhs = try f.resolveInst(bin_op.lhs); @@ -3829,7 +3852,7 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: try writer.writeAll(" = "); try f.writeCValue(writer, lhs, .Other); try writer.writeByte(' '); - try writer.writeAll(operator); + try writer.writeAll(compareOperatorC(operator)); try writer.writeByte(' '); try f.writeCValue(writer, rhs, .Other); try writer.writeAll(";\n"); @@ -3840,9 +3863,7 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: fn airEquality( f: *Function, inst: Air.Inst.Index, - negate_prefix: []const u8, - operator: []const u8, - operation: []const u8, + operator: std.math.CompareOperator, ) !CValue { const bin_op = f.air.instructions.items(.data)[inst].bin_op; @@ -3853,10 +3874,11 @@ fn airEquality( const operand_ty = f.air.typeOf(bin_op.lhs); const target = f.object.dg.module.getTarget(); - if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) - return try cmpBuiltinCall(f, inst, operator, "cmp"); + const operand_bits = operand_ty.bitSize(target); + if (operand_ty.isInt() and operand_bits > 64) + return cmpBuiltinCall(f, inst, bin_op, operator, .cmp, if (operand_bits > 128) .bits else .none); if (operand_ty.isRuntimeFloat()) - return try cmpBuiltinCall(f, inst, operator, operation); + return cmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -3872,7 +3894,12 @@ fn airEquality( // (A && B) || (C && (A == B)) // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload - try writer.writeAll(negate_prefix); + switch (operator) { + .eq => {}, + .neq => try writer.writeByte('!'), + else => unreachable, + } + try writer.writeAll("(("); try f.writeCValue(writer, lhs, .Other); try writer.writeAll(".is_null && "); try f.writeCValue(writer, rhs, .Other); @@ -3891,7 +3918,7 @@ fn airEquality( try f.writeCValue(writer, lhs, .Other); try writer.writeByte(' '); - try writer.writeAll(operator); + try writer.writeAll(compareOperatorC(operator)); try writer.writeByte(' '); try f.writeCValue(writer, rhs, .Other); try writer.writeAll(";\n"); @@ -3972,7 +3999,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons const inst_ty = f.air.typeOfIndex(inst); const target = f.object.dg.module.getTarget(); if (inst_ty.isInt() and inst_ty.bitSize(target) > 64) - return try airBinBuiltinCall(f, inst, operation[1..], .None); + return try airBinBuiltinCall(f, inst, operation[1..], .none); if (inst_ty.isRuntimeFloat()) return try airBinFloatOp(f, inst, operation); @@ -4418,12 +4445,35 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { // Ensure padding bits have the expected value. if (dest_ty.isAbiInt()) { + const dest_cty = try f.typeToCType(dest_ty, .complete); + const dest_info = dest_ty.intInfo(target); + var wrap_ty_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dest_info.signedness) { + .unsigned => .int_unsigned, + .signed => .int_signed, + } }, .data = dest_info.bits }; + try f.writeCValue(writer, local, .Other); + if (dest_cty.castTag(.array)) |pl| { + try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { + .Little => pl.data.len - 1, + .Big => 0, + }}); + wrap_ty_pl.data -= 1; + wrap_ty_pl.data %= @intCast(u16, f.byteSize(f.indexToCType(pl.data.elem_type)) * 8); + wrap_ty_pl.data += 1; + } + const wrap_ty = Type.initPayload(&wrap_ty_pl.base); try writer.writeAll(" = zig_wrap_"); - try f.object.dg.renderTypeForBuiltinFnName(writer, dest_ty); + try f.object.dg.renderTypeForBuiltinFnName(writer, wrap_ty); try writer.writeByte('('); try f.writeCValue(writer, local, .Other); - try f.object.dg.renderBuiltinInfo(writer, dest_ty, .Bits); + if (dest_cty.castTag(.array)) |pl| { + try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { + .Little => pl.data.len - 1, + .Big => 0, + }}); + } + try f.object.dg.renderBuiltinInfo(writer, wrap_ty, .bits); try writer.writeAll(");\n"); } @@ -5438,7 +5488,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); try writer.writeByte(')'); if (cant_cast) try writer.writeByte(')'); - try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .Bits); + try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits); try writer.writeAll(");\n"); if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local; @@ -5871,7 +5921,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, operand, .FunctionArgument); try writer.writeByte(')'); if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) { - try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits); + try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); try writer.writeByte(')'); } try writer.writeAll(";\n"); @@ -5972,29 +6022,46 @@ fn airBinBuiltinCall( fn cmpBuiltinCall( f: *Function, inst: Air.Inst.Index, - operator: []const u8, - operation: []const u8, + data: anytype, + operator: std.math.CompareOperator, + operation: enum { cmp, operator }, + info: BuiltinInfo, ) !CValue { const inst_ty = f.air.typeOfIndex(inst); - const bin_op = f.air.instructions.items(.data)[inst].bin_op; - const operand_ty = f.air.typeOf(bin_op.lhs); + const operand_ty = f.air.typeOf(data.lhs); - const lhs = try f.resolveInst(bin_op.lhs); - const rhs = try f.resolveInst(bin_op.rhs); - try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); + const lhs = try f.resolveInst(data.lhs); + const rhs = try f.resolveInst(data.rhs); + try reap(f, inst, &.{ data.lhs, data.rhs }); + + const ref_ret = inst_ty.tag() != .bool; const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); - try f.writeCValue(writer, local, .Other); - try writer.writeAll(" = zig_"); - try writer.writeAll(operation); - try writer.writeByte('_'); + if (!ref_ret) { + try f.writeCValue(writer, local, .Other); + try writer.writeAll(" = "); + } + try writer.print("zig_{s}_", .{switch (operation) { + else => @tagName(operation), + .operator => compareOperatorAbbrev(operator), + }}); try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); try writer.writeByte('('); + if (ref_ret) { + try f.writeCValue(writer, local, .FunctionArgument); + try writer.writeAll(", "); + } try f.writeCValue(writer, lhs, .FunctionArgument); try writer.writeAll(", "); try f.writeCValue(writer, rhs, .FunctionArgument); - try writer.print(") {s} {};\n", .{ operator, try f.fmtIntLiteral(Type.initTag(.i32), Value.zero) }); + try f.object.dg.renderBuiltinInfo(writer, operand_ty, info); + try writer.writeByte(')'); + if (!ref_ret) try writer.print(" {s} {}", .{ + compareOperatorC(operator), + try f.fmtIntLiteral(Type.initTag(.i32), Value.zero), + }); + try writer.writeAll(";\n"); return local; } @@ -6675,7 +6742,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", "); try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); - try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits); + try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); try writer.writeByte(')'); if (!empty) try writer.writeByte(')'); @@ -7094,6 +7161,28 @@ fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 { } else unreachable; } +fn compareOperatorAbbrev(operator: std.math.CompareOperator) []const u8 { + return switch (operator) { + .lt => "lt", + .lte => "le", + .eq => "eq", + .gte => "ge", + .gt => "gt", + .neq => "ne", + }; +} + +fn compareOperatorC(operator: std.math.CompareOperator) []const u8 { + return switch (operator) { + .lt => "<", + .lte => "<=", + .eq => "==", + .gte => ">=", + .gt => ">", + .neq => "!=", + }; +} + fn StringLiteral(comptime WriterType: type) type { // MSVC has a length limit of 16380 per string literal (before concatenation) const max_char_len = 4; @@ -7239,14 +7328,6 @@ fn formatIntLiteral( .positive = undefined, }; defer allocator.free(wrap.limbs); - if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or - data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) - return writer.print("{s}_{s}", .{ - data.cty.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{ - if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, - }), - if (int.positive) "MAX" else "MIN", - }); const c_limb_info: struct { cty: CType, @@ -7277,6 +7358,15 @@ fn formatIntLiteral( }, }; if (c_limb_info.count == 1) { + if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or + data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) + return writer.print("{s}_{s}", .{ + data.cty.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{ + if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, + }), + if (int.positive) "MAX" else "MIN", + }); + if (!int.positive) try writer.writeByte('-'); try data.cty.renderLiteralPrefix(writer, data.kind); @@ -7310,7 +7400,7 @@ fn formatIntLiteral( try writer.writeAll(string); } else { try data.cty.renderLiteralPrefix(writer, data.kind); - wrap.convertToTwosComplement(int, .unsigned, data.int_info.bits); + wrap.convertToTwosComplement(int, data.int_info.signedness, c_bits); std.mem.set(BigIntLimb, wrap.limbs[wrap.len..], 0); wrap.len = wrap.limbs.len; const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count); @@ -7343,7 +7433,7 @@ fn formatIntLiteral( c_limb_cty = c_limb_info.cty.toSigned(); c_limb_mut.positive = wrap.positive; - c_limb_mut.convertToTwosComplement( + c_limb_mut.truncate( c_limb_mut.toConst(), .signed, data.int_info.bits - limb_i * @bitSizeOf(BigIntLimb), diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index a1b11df315..85e4cc9840 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -496,6 +496,116 @@ pub const CType = extern union { } }; + pub fn isBool(self: CType) bool { + return switch (self.tag()) { + ._Bool, + .bool, + => true, + else => false, + }; + } + + pub fn isInteger(self: CType) bool { + return switch (self.tag()) { + .char, + .@"signed char", + .short, + .int, + .long, + .@"long long", + .@"unsigned char", + .@"unsigned short", + .@"unsigned int", + .@"unsigned long", + .@"unsigned long long", + .size_t, + .ptrdiff_t, + .uint8_t, + .int8_t, + .uint16_t, + .int16_t, + .uint32_t, + .int32_t, + .uint64_t, + .int64_t, + .uintptr_t, + .intptr_t, + .zig_u128, + .zig_i128, + => true, + else => false, + }; + } + + pub fn signedness(self: CType) ?std.builtin.Signedness { + return switch (self.tag()) { + .char => null, // unknown signedness + .@"signed char", + .short, + .int, + .long, + .@"long long", + .ptrdiff_t, + .int8_t, + .int16_t, + .int32_t, + .int64_t, + .intptr_t, + .zig_i128, + => .signed, + .@"unsigned char", + .@"unsigned short", + .@"unsigned int", + .@"unsigned long", + .@"unsigned long long", + .size_t, + .uint8_t, + .uint16_t, + .uint32_t, + .uint64_t, + .uintptr_t, + .zig_u128, + => .unsigned, + else => unreachable, + }; + } + + pub fn isFloat(self: CType) bool { + return switch (self.tag()) { + .float, + .double, + .@"long double", + .zig_f16, + .zig_f32, + .zig_f64, + .zig_f80, + .zig_f128, + .zig_c_longdouble, + => true, + else => false, + }; + } + + pub fn isPointer(self: CType) bool { + return switch (self.tag()) { + .pointer, + .pointer_const, + .pointer_volatile, + .pointer_const_volatile, + => true, + else => false, + }; + } + + pub fn isFunction(self: CType) bool { + return switch (self.tag()) { + .function, + .varargs_function, + => true, + else => false, + }; + } + pub fn toSigned(self: CType) CType { return CType.initTag(switch (self.tag()) { .char, .@"signed char", .@"unsigned char" => .@"signed char", @@ -725,6 +835,20 @@ pub const CType = extern union { } } + pub fn floatActiveBits(self: CType, target: Target) u16 { + return switch (self.tag()) { + .float => target.c_type_bit_size(.float), + .double => target.c_type_bit_size(.double), + .@"long double", .zig_c_longdouble => target.c_type_bit_size(.longdouble), + .zig_f16 => 16, + .zig_f32 => 32, + .zig_f64 => 64, + .zig_f80 => 80, + .zig_f128 => 128, + else => unreachable, + }; + } + pub fn byteSize(self: CType, store: Store.Set, target: Target) u64 { return switch (self.tag()) { .void => 0, diff --git a/src/type.zig b/src/type.zig index 15525f14eb..9e501d893c 100644 --- a/src/type.zig +++ b/src/type.zig @@ -4213,7 +4213,7 @@ pub const Type = extern union { }; } - fn shallowElemType(child_ty: Type) Type { + pub fn shallowElemType(child_ty: Type) Type { return switch (child_ty.zigTypeTag()) { .Array, .Vector => child_ty.childType(), else => child_ty, diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index 70ac38d6fa..552080c836 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -34,7 +34,6 @@ test "@bitCast iX -> uX (8, 16, 128)" { test "@bitCast iX -> uX exotic integers" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; @@ -81,7 +80,6 @@ fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signe test "bitcast uX to bytes" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 54263e1daf..9ebeca8541 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -1526,7 +1526,6 @@ fn testNanEqNan(comptime F: type) !void { } test "vector comparison" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 50fef7f646..d885a7fabc 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -48,7 +48,6 @@ test "vector wrap operators" { test "vector bin compares with mem.eql" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -403,7 +402,6 @@ test "initialize vector which is a struct field" { test "vector comparison operators" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO -- cgit v1.2.3 From 9e3a5ecd39227aff3b2821d0c0b489eb9713b146 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 4 Mar 2023 15:18:05 -0500 Subject: CBE: fix behavior test failures on msvc --- lib/zig.h | 4 +++- src/codegen/c.zig | 37 +++++++++++++++++++++++++++++-------- src/codegen/c/type.zig | 7 +++++++ 3 files changed, 39 insertions(+), 9 deletions(-) (limited to 'src/codegen/c/type.zig') diff --git a/lib/zig.h b/lib/zig.h index 5d77c76c8f..6b95ba3358 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -1646,7 +1646,9 @@ static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) { } static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) { - return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val)); + if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val)); + int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits); + return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); } static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 4d3e71e78a..b8606b1a17 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -4461,10 +4461,12 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { if (dest_ty.isAbiInt()) { const dest_cty = try f.typeToCType(dest_ty, .complete); const dest_info = dest_ty.intInfo(target); - var wrap_ty_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dest_info.signedness) { + var info_ty_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dest_info.signedness) { .unsigned => .int_unsigned, .signed => .int_signed, } }, .data = dest_info.bits }; + var wrap_cty: ?CType = null; + var need_bitcasts = false; try f.writeCValue(writer, local, .Other); if (dest_cty.castTag(.array)) |pl| { @@ -4472,14 +4474,31 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { .Little => pl.data.len - 1, .Big => 0, }}); - wrap_ty_pl.data -= 1; - wrap_ty_pl.data %= @intCast(u16, f.byteSize(f.indexToCType(pl.data.elem_type)) * 8); - wrap_ty_pl.data += 1; + const elem_cty = f.indexToCType(pl.data.elem_type); + wrap_cty = elem_cty.toSignedness(dest_info.signedness); + need_bitcasts = wrap_cty.?.tag() == .zig_i128; + info_ty_pl.data -= 1; + info_ty_pl.data %= @intCast(u16, f.byteSize(elem_cty) * 8); + info_ty_pl.data += 1; } - const wrap_ty = Type.initPayload(&wrap_ty_pl.base); - try writer.writeAll(" = zig_wrap_"); - try f.object.dg.renderTypeForBuiltinFnName(writer, wrap_ty); + try writer.writeAll(" = "); + if (need_bitcasts) { + try writer.writeAll("zig_bitcast_"); + try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_cty.?.toUnsigned()); + try writer.writeByte('('); + } + try writer.writeAll("zig_wrap_"); + const info_ty = Type.initPayload(&info_ty_pl.base); + if (wrap_cty) |cty| + try f.object.dg.renderCTypeForBuiltinFnName(writer, cty) + else + try f.object.dg.renderTypeForBuiltinFnName(writer, info_ty); try writer.writeByte('('); + if (need_bitcasts) { + try writer.writeAll("zig_bitcast_"); + try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_cty.?); + try writer.writeByte('('); + } try f.writeCValue(writer, local, .Other); if (dest_cty.castTag(.array)) |pl| { try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { @@ -4487,7 +4506,9 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { .Big => 0, }}); } - try f.object.dg.renderBuiltinInfo(writer, wrap_ty, .bits); + if (need_bitcasts) try writer.writeByte(')'); + try f.object.dg.renderBuiltinInfo(writer, info_ty, .bits); + if (need_bitcasts) try writer.writeByte(')'); try writer.writeAll(");\n"); } diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 85e4cc9840..313fcc130c 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -651,6 +651,13 @@ pub const CType = extern union { }); } + pub fn toSignedness(self: CType, s: std.builtin.Signedness) CType { + return switch (s) { + .unsigned => self.toUnsigned(), + .signed => self.toSigned(), + }; + } + pub fn getStandardDefineAbbrev(self: CType) ?[]const u8 { return switch (self.tag()) { .char => "CHAR", -- cgit v1.2.3 From 8f6da78fb1bfc9d5e8b3d5affd33cf6a62f5e8c7 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sun, 5 Mar 2023 00:30:55 -0500 Subject: CBE: implement vector element pointers --- src/codegen/c.zig | 10 ++-------- src/codegen/c/type.zig | 2 +- test/behavior/vector.zig | 3 --- 3 files changed, 3 insertions(+), 12 deletions(-) (limited to 'src/codegen/c/type.zig') diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 5e92a6f76c..60f93311a4 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -17,12 +17,6 @@ const LazySrcLoc = Module.LazySrcLoc; const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); -const target_util = @import("../target.zig"); -const libcFloatPrefix = target_util.libcFloatPrefix; -const libcFloatSuffix = target_util.libcFloatSuffix; -const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev; -const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; - const BigIntLimb = std.math.big.Limb; const BigInt = std.math.big.int; @@ -3317,7 +3311,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", sizeof("); try f.renderType(writer, src_ty); try writer.writeAll("))"); - } else if (ptr_info.host_size != 0) { + } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) { var host_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = ptr_info.host_size * 8, @@ -3647,7 +3641,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { if (src_val == .constant) { try freeLocal(f, inst, array_src.new_local, 0); } - } else if (ptr_info.host_size != 0) { + } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) { const host_bits = ptr_info.host_size * 8; var host_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = host_bits }; const host_ty = Type.initPayload(&host_pl.base); diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 313fcc130c..038f53f186 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -1465,7 +1465,7 @@ pub const CType = extern union { .base = .{ .tag = .int_unsigned }, .data = info.host_size * 8, }; - const pointee_ty = if (info.host_size > 0) + const pointee_ty = if (info.host_size > 0 and info.vector_index == .none) Type.initPayload(&host_int_pl.base) else info.pointee_type; diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index e74bcdad86..42befa9c0f 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -1118,7 +1118,6 @@ test "byte vector initialized in inline function" { } test "byte vector initialized in inline function" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO @@ -1233,7 +1232,6 @@ test "load packed vector element" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO var x: @Vector(2, u15) = .{ 1, 4 }; try expect((&x[0]).* == 1); @@ -1246,7 +1244,6 @@ test "store packed vector element" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO var v = @Vector(4, u1){ 1, 1, 1, 1 }; try expectEqual(@Vector(4, u1){ 1, 1, 1, 1 }, v); -- cgit v1.2.3