| author | |
| committer | |
| log | 1653a9b2597c66cbcc88ea75d8a4b88c163584a5 |
| tree | 9cbe5d66e5088006ac4b5d5b4861a3b8b25a7a54 |
| parent | fad95741db7529bbad873fb330c25d64ac765340 |
| parent | 92bc3cbe27792be0300fb5f104c011a11f3cf40f |
| signature |
LLVM: implement signext/zeroext attributes8 files changed, 148 insertions(+), 62 deletions(-)
lib/compiler_rt/common.zig+5-1| ... | @@ -68,7 +68,11 @@ pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) nore | ... | @@ -68,7 +68,11 @@ pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) nore |
| 68 | /// need for extending them to wider fp types. | 68 | /// need for extending them to wider fp types. |
| 69 | /// TODO remove this; do this type selection in the language rather than | 69 | /// TODO remove this; do this type selection in the language rather than |
| 70 | /// here in compiler-rt. | 70 | /// here in compiler-rt. |
| 71 | pub const F16T = if (builtin.cpu.arch.isAARCH64()) f16 else u16; | 71 | pub const F16T = switch (builtin.cpu.arch) { |
| 72 | .aarch64, .aarch64_be, .aarch64_32 => f16, | ||
| 73 | .riscv64 => if (builtin.zig_backend == .stage1) u16 else f16, | ||
| 74 | else => u16, | ||
| 75 | }; | ||
| 72 | 76 | ||
| 73 | pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { | 77 | pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { |
| 74 | switch (Z) { | 78 | switch (Z) { |
lib/std/math/float.zig+17-17| ... | @@ -3,20 +3,20 @@ const assert = std.debug.assert; | ... | @@ -3,20 +3,20 @@ const assert = std.debug.assert; |
| 3 | const expect = std.testing.expect; | 3 | const expect = std.testing.expect; |
| 4 | 4 | ||
| 5 | /// Creates a raw "1.0" mantissa for floating point type T. Used to dedupe f80 logic. | 5 | /// Creates a raw "1.0" mantissa for floating point type T. Used to dedupe f80 logic. |
| 6 | fn mantissaOne(comptime T: type) comptime_int { | 6 | inline fn mantissaOne(comptime T: type) comptime_int { |
| 7 | return if (@typeInfo(T).Float.bits == 80) 1 << floatFractionalBits(T) else 0; | 7 | return if (@typeInfo(T).Float.bits == 80) 1 << floatFractionalBits(T) else 0; |
| 8 | } | 8 | } |
| 9 | 9 | ||
| 10 | /// Creates floating point type T from an unbiased exponent and raw mantissa. | 10 | /// Creates floating point type T from an unbiased exponent and raw mantissa. |
| 11 | fn reconstructFloat(comptime T: type, exponent: comptime_int, mantissa: comptime_int) T { | 11 | inline fn reconstructFloat(comptime T: type, exponent: comptime_int, mantissa: comptime_int) T { |
| 12 | const TBits = std.meta.Int(.unsigned, @bitSizeOf(T)); | 12 | const TBits = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } }); |
| 13 | const biased_exponent = @as(TBits, exponent + floatExponentMax(T)); | 13 | const biased_exponent = @as(TBits, exponent + floatExponentMax(T)); |
| 14 | return @bitCast(T, (biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa)); | 14 | return @bitCast(T, (biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa)); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | /// Returns the number of bits in the exponent of floating point type T. | 17 | /// Returns the number of bits in the exponent of floating point type T. |
| 18 | pub fn floatExponentBits(comptime T: type) comptime_int { | 18 | pub inline fn floatExponentBits(comptime T: type) comptime_int { |
| 19 | assert(@typeInfo(T) == .Float); | 19 | comptime assert(@typeInfo(T) == .Float); |
| 20 | 20 | ||
| 21 | return switch (@typeInfo(T).Float.bits) { | 21 | return switch (@typeInfo(T).Float.bits) { |
| 22 | 16 => 5, | 22 | 16 => 5, |
| ... | @@ -29,8 +29,8 @@ pub fn floatExponentBits(comptime T: type) comptime_int { | ... | @@ -29,8 +29,8 @@ pub fn floatExponentBits(comptime T: type) comptime_int { |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | /// Returns the number of bits in the mantissa of floating point type T. | 31 | /// Returns the number of bits in the mantissa of floating point type T. |
| 32 | pub fn floatMantissaBits(comptime T: type) comptime_int { | 32 | pub inline fn floatMantissaBits(comptime T: type) comptime_int { |
| 33 | assert(@typeInfo(T) == .Float); | 33 | comptime assert(@typeInfo(T) == .Float); |
| 34 | 34 | ||
| 35 | return switch (@typeInfo(T).Float.bits) { | 35 | return switch (@typeInfo(T).Float.bits) { |
| 36 | 16 => 10, | 36 | 16 => 10, |
| ... | @@ -43,8 +43,8 @@ pub fn floatMantissaBits(comptime T: type) comptime_int { | ... | @@ -43,8 +43,8 @@ pub fn floatMantissaBits(comptime T: type) comptime_int { |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | /// Returns the number of fractional bits in the mantissa of floating point type T. | 45 | /// Returns the number of fractional bits in the mantissa of floating point type T. |
| 46 | pub fn floatFractionalBits(comptime T: type) comptime_int { | 46 | pub inline fn floatFractionalBits(comptime T: type) comptime_int { |
| 47 | assert(@typeInfo(T) == .Float); | 47 | comptime assert(@typeInfo(T) == .Float); |
| 48 | 48 | ||
| 49 | // standard IEEE floats have an implicit 0.m or 1.m integer part | 49 | // standard IEEE floats have an implicit 0.m or 1.m integer part |
| 50 | // f80 is special and has an explicitly stored bit in the MSB | 50 | // f80 is special and has an explicitly stored bit in the MSB |
| ... | @@ -61,43 +61,43 @@ pub fn floatFractionalBits(comptime T: type) comptime_int { | ... | @@ -61,43 +61,43 @@ pub fn floatFractionalBits(comptime T: type) comptime_int { |
| 61 | 61 | ||
| 62 | /// Returns the minimum exponent that can represent | 62 | /// Returns the minimum exponent that can represent |
| 63 | /// a normalised value in floating point type T. | 63 | /// a normalised value in floating point type T. |
| 64 | pub fn floatExponentMin(comptime T: type) comptime_int { | 64 | pub inline fn floatExponentMin(comptime T: type) comptime_int { |
| 65 | return -floatExponentMax(T) + 1; | 65 | return -floatExponentMax(T) + 1; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | /// Returns the maximum exponent that can represent | 68 | /// Returns the maximum exponent that can represent |
| 69 | /// a normalised value in floating point type T. | 69 | /// a normalised value in floating point type T. |
| 70 | pub fn floatExponentMax(comptime T: type) comptime_int { | 70 | pub inline fn floatExponentMax(comptime T: type) comptime_int { |
| 71 | return (1 << (floatExponentBits(T) - 1)) - 1; | 71 | return (1 << (floatExponentBits(T) - 1)) - 1; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | /// Returns the smallest subnormal number representable in floating point type T. | 74 | /// Returns the smallest subnormal number representable in floating point type T. |
| 75 | pub fn floatTrueMin(comptime T: type) T { | 75 | pub inline fn floatTrueMin(comptime T: type) T { |
| 76 | return reconstructFloat(T, floatExponentMin(T) - 1, 1); | 76 | return reconstructFloat(T, floatExponentMin(T) - 1, 1); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | /// Returns the smallest normal number representable in floating point type T. | 79 | /// Returns the smallest normal number representable in floating point type T. |
| 80 | pub fn floatMin(comptime T: type) T { | 80 | pub inline fn floatMin(comptime T: type) T { |
| 81 | return reconstructFloat(T, floatExponentMin(T), mantissaOne(T)); | 81 | return reconstructFloat(T, floatExponentMin(T), mantissaOne(T)); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | /// Returns the largest normal number representable in floating point type T. | 84 | /// Returns the largest normal number representable in floating point type T. |
| 85 | pub fn floatMax(comptime T: type) T { | 85 | pub inline fn floatMax(comptime T: type) T { |
| 86 | const all1s_mantissa = (1 << floatMantissaBits(T)) - 1; | 86 | const all1s_mantissa = (1 << floatMantissaBits(T)) - 1; |
| 87 | return reconstructFloat(T, floatExponentMax(T), all1s_mantissa); | 87 | return reconstructFloat(T, floatExponentMax(T), all1s_mantissa); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | /// Returns the machine epsilon of floating point type T. | 90 | /// Returns the machine epsilon of floating point type T. |
| 91 | pub fn floatEps(comptime T: type) T { | 91 | pub inline fn floatEps(comptime T: type) T { |
| 92 | return reconstructFloat(T, -floatFractionalBits(T), mantissaOne(T)); | 92 | return reconstructFloat(T, -floatFractionalBits(T), mantissaOne(T)); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | /// Returns the value inf for floating point type T. | 95 | /// Returns the value inf for floating point type T. |
| 96 | pub fn inf(comptime T: type) T { | 96 | pub inline fn inf(comptime T: type) T { |
| 97 | return reconstructFloat(T, floatExponentMax(T) + 1, mantissaOne(T)); | 97 | return reconstructFloat(T, floatExponentMax(T) + 1, mantissaOne(T)); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | test "std.math.float" { | 100 | test "float bits" { |
| 101 | inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| { | 101 | inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| { |
| 102 | // (1 +) for the sign bit, since it is separate from the other bits | 102 | // (1 +) for the sign bit, since it is separate from the other bits |
| 103 | const size = 1 + floatExponentBits(T) + floatMantissaBits(T); | 103 | const size = 1 + floatExponentBits(T) + floatMantissaBits(T); |
lib/std/math/isinf.zig+3-3| ... | @@ -3,7 +3,7 @@ const math = std.math; | ... | @@ -3,7 +3,7 @@ const math = std.math; |
| 3 | const expect = std.testing.expect; | 3 | const expect = std.testing.expect; |
| 4 | 4 | ||
| 5 | /// Returns whether x is an infinity, ignoring sign. | 5 | /// Returns whether x is an infinity, ignoring sign. |
| 6 | pub fn isInf(x: anytype) bool { | 6 | pub inline fn isInf(x: anytype) bool { |
| 7 | const T = @TypeOf(x); | 7 | const T = @TypeOf(x); |
| 8 | const TBits = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); | 8 | const TBits = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); |
| 9 | const remove_sign = ~@as(TBits, 0) >> 1; | 9 | const remove_sign = ~@as(TBits, 0) >> 1; |
| ... | @@ -11,12 +11,12 @@ pub fn isInf(x: anytype) bool { | ... | @@ -11,12 +11,12 @@ pub fn isInf(x: anytype) bool { |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | /// Returns whether x is an infinity with a positive sign. | 13 | /// Returns whether x is an infinity with a positive sign. |
| 14 | pub fn isPositiveInf(x: anytype) bool { | 14 | pub inline fn isPositiveInf(x: anytype) bool { |
| 15 | return x == math.inf(@TypeOf(x)); | 15 | return x == math.inf(@TypeOf(x)); |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | /// Returns whether x is an infinity with a negative sign. | 18 | /// Returns whether x is an infinity with a negative sign. |
| 19 | pub fn isNegativeInf(x: anytype) bool { | 19 | pub inline fn isNegativeInf(x: anytype) bool { |
| 20 | return x == -math.inf(@TypeOf(x)); | 20 | return x == -math.inf(@TypeOf(x)); |
| 21 | } | 21 | } |
| 22 | 22 |
src/Sema.zig+42| ... | @@ -22571,6 +22571,48 @@ fn bitCastVal( | ... | @@ -22571,6 +22571,48 @@ fn bitCastVal( |
| 22571 | const target = sema.mod.getTarget(); | 22571 | const target = sema.mod.getTarget(); |
| 22572 | if (old_ty.eql(new_ty, sema.mod)) return val; | 22572 | if (old_ty.eql(new_ty, sema.mod)) return val; |
| 22573 | 22573 | ||
| 22574 | // Some conversions have a bitwise definition that ignores in-memory layout, | ||
| 22575 | // such as converting between f80 and u80. | ||
| 22576 | |||
| 22577 | if (old_ty.eql(Type.f80, sema.mod) and new_ty.isAbiInt()) { | ||
| 22578 | const float = val.toFloat(f80); | ||
| 22579 | switch (new_ty.intInfo(target).signedness) { | ||
| 22580 | .signed => { | ||
| 22581 | const int = @bitCast(i80, float); | ||
| 22582 | const limbs = try sema.arena.alloc(std.math.big.Limb, 2); | ||
| 22583 | const big_int = std.math.big.int.Mutable.init(limbs, int); | ||
| 22584 | return Value.fromBigInt(sema.arena, big_int.toConst()); | ||
| 22585 | }, | ||
| 22586 | .unsigned => { | ||
| 22587 | const int = @bitCast(u80, float); | ||
| 22588 | const limbs = try sema.arena.alloc(std.math.big.Limb, 2); | ||
| 22589 | const big_int = std.math.big.int.Mutable.init(limbs, int); | ||
| 22590 | return Value.fromBigInt(sema.arena, big_int.toConst()); | ||
| 22591 | }, | ||
| 22592 | } | ||
| 22593 | } | ||
| 22594 | |||
| 22595 | if (new_ty.eql(Type.f80, sema.mod) and old_ty.isAbiInt()) { | ||
| 22596 | var bigint_space: Value.BigIntSpace = undefined; | ||
| 22597 | var bigint = try val.toBigIntAdvanced(&bigint_space, target, sema.kit(block, src)); | ||
| 22598 | switch (old_ty.intInfo(target).signedness) { | ||
| 22599 | .signed => { | ||
| 22600 | // This conversion cannot fail because we already checked bit size before | ||
| 22601 | // calling bitCastVal. | ||
| 22602 | const int = bigint.to(i80) catch unreachable; | ||
| 22603 | const float = @bitCast(f80, int); | ||
| 22604 | return Value.Tag.float_80.create(sema.arena, float); | ||
| 22605 | }, | ||
| 22606 | .unsigned => { | ||
| 22607 | // This conversion cannot fail because we already checked bit size before | ||
| 22608 | // calling bitCastVal. | ||
| 22609 | const int = bigint.to(u80) catch unreachable; | ||
| 22610 | const float = @bitCast(f80, int); | ||
| 22611 | return Value.Tag.float_80.create(sema.arena, float); | ||
| 22612 | }, | ||
| 22613 | } | ||
| 22614 | } | ||
| 22615 | |||
| 22574 | // For types with well-defined memory layouts, we serialize them a byte buffer, | 22616 | // For types with well-defined memory layouts, we serialize them a byte buffer, |
| 22575 | // then deserialize to the new type. | 22617 | // then deserialize to the new type. |
| 22576 | const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target)); | 22618 | const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target)); |
src/codegen/llvm.zig+64-1| ... | @@ -717,6 +717,11 @@ pub const Object = struct { | ... | @@ -717,6 +717,11 @@ pub const Object = struct { |
| 717 | const ret_ptr = if (sret) llvm_func.getParam(0) else null; | 717 | const ret_ptr = if (sret) llvm_func.getParam(0) else null; |
| 718 | const gpa = dg.gpa; | 718 | const gpa = dg.gpa; |
| 719 | 719 | ||
| 720 | if (ccAbiPromoteInt(fn_info.cc, target, fn_info.return_type)) |s| switch (s) { | ||
| 721 | .signed => dg.addAttr(llvm_func, 0, "signext"), | ||
| 722 | .unsigned => dg.addAttr(llvm_func, 0, "zeroext"), | ||
| 723 | }; | ||
| 724 | |||
| 720 | const err_return_tracing = fn_info.return_type.isError() and | 725 | const err_return_tracing = fn_info.return_type.isError() and |
| 721 | dg.module.comp.bin_file.options.error_return_tracing; | 726 | dg.module.comp.bin_file.options.error_return_tracing; |
| 722 | 727 | ||
| ... | @@ -774,7 +779,10 @@ pub const Object = struct { | ... | @@ -774,7 +779,10 @@ pub const Object = struct { |
| 774 | ); | 779 | ); |
| 775 | dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align); | 780 | dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align); |
| 776 | } | 781 | } |
| 777 | } | 782 | } else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) { |
| 783 | .signed => dg.addArgAttr(llvm_func, llvm_arg_i, "signext"), | ||
| 784 | .unsigned => dg.addArgAttr(llvm_func, llvm_arg_i, "zeroext"), | ||
| 785 | }; | ||
| 778 | } | 786 | } |
| 779 | llvm_arg_i += 1; | 787 | llvm_arg_i += 1; |
| 780 | }, | 788 | }, |
| ... | @@ -887,6 +895,13 @@ pub const Object = struct { | ... | @@ -887,6 +895,13 @@ pub const Object = struct { |
| 887 | }; | 895 | }; |
| 888 | try args.append(loaded); | 896 | try args.append(loaded); |
| 889 | }, | 897 | }, |
| 898 | .as_u16 => { | ||
| 899 | const param = llvm_func.getParam(llvm_arg_i); | ||
| 900 | llvm_arg_i += 1; | ||
| 901 | const casted = builder.buildBitCast(param, dg.context.halfType(), ""); | ||
| 902 | try args.ensureUnusedCapacity(1); | ||
| 903 | args.appendAssumeCapacity(casted); | ||
| 904 | }, | ||
| 890 | }; | 905 | }; |
| 891 | } | 906 | } |
| 892 | 907 | ||
| ... | @@ -2794,6 +2809,9 @@ pub const DeclGen = struct { | ... | @@ -2794,6 +2809,9 @@ pub const DeclGen = struct { |
| 2794 | llvm_params.appendAssumeCapacity(big_int_ty); | 2809 | llvm_params.appendAssumeCapacity(big_int_ty); |
| 2795 | } | 2810 | } |
| 2796 | }, | 2811 | }, |
| 2812 | .as_u16 => { | ||
| 2813 | try llvm_params.append(dg.context.intType(16)); | ||
| 2814 | }, | ||
| 2797 | }; | 2815 | }; |
| 2798 | 2816 | ||
| 2799 | return llvm.functionType( | 2817 | return llvm.functionType( |
| ... | @@ -4234,6 +4252,12 @@ pub const FuncGen = struct { | ... | @@ -4234,6 +4252,12 @@ pub const FuncGen = struct { |
| 4234 | llvm_args.appendAssumeCapacity(load_inst); | 4252 | llvm_args.appendAssumeCapacity(load_inst); |
| 4235 | } | 4253 | } |
| 4236 | }, | 4254 | }, |
| 4255 | .as_u16 => { | ||
| 4256 | const arg = args[it.zig_index - 1]; | ||
| 4257 | const llvm_arg = try self.resolveInst(arg); | ||
| 4258 | const casted = self.builder.buildBitCast(llvm_arg, self.dg.context.intType(16), ""); | ||
| 4259 | try llvm_args.append(casted); | ||
| 4260 | }, | ||
| 4237 | }; | 4261 | }; |
| 4238 | 4262 | ||
| 4239 | const call = self.builder.buildCall( | 4263 | const call = self.builder.buildCall( |
| ... | @@ -8965,6 +8989,7 @@ const ParamTypeIterator = struct { | ... | @@ -8965,6 +8989,7 @@ const ParamTypeIterator = struct { |
| 8965 | abi_sized_int, | 8989 | abi_sized_int, |
| 8966 | multiple_llvm_ints, | 8990 | multiple_llvm_ints, |
| 8967 | slice, | 8991 | slice, |
| 8992 | as_u16, | ||
| 8968 | }; | 8993 | }; |
| 8969 | 8994 | ||
| 8970 | pub fn next(it: *ParamTypeIterator) ?Lowering { | 8995 | pub fn next(it: *ParamTypeIterator) ?Lowering { |
| ... | @@ -9025,6 +9050,15 @@ const ParamTypeIterator = struct { | ... | @@ -9025,6 +9050,15 @@ const ParamTypeIterator = struct { |
| 9025 | else => false, | 9050 | else => false, |
| 9026 | }; | 9051 | }; |
| 9027 | switch (it.target.cpu.arch) { | 9052 | switch (it.target.cpu.arch) { |
| 9053 | .riscv32, .riscv64 => { | ||
| 9054 | it.zig_index += 1; | ||
| 9055 | it.llvm_index += 1; | ||
| 9056 | if (ty.tag() == .f16) { | ||
| 9057 | return .as_u16; | ||
| 9058 | } else { | ||
| 9059 | return .byval; | ||
| 9060 | } | ||
| 9061 | }, | ||
| 9028 | .mips, .mipsel => { | 9062 | .mips, .mipsel => { |
| 9029 | it.zig_index += 1; | 9063 | it.zig_index += 1; |
| 9030 | it.llvm_index += 1; | 9064 | it.llvm_index += 1; |
| ... | @@ -9135,6 +9169,35 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp | ... | @@ -9135,6 +9169,35 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp |
| 9135 | }; | 9169 | }; |
| 9136 | } | 9170 | } |
| 9137 | 9171 | ||
| 9172 | fn ccAbiPromoteInt( | ||
| 9173 | cc: std.builtin.CallingConvention, | ||
| 9174 | target: std.Target, | ||
| 9175 | ty: Type, | ||
| 9176 | ) ?std.builtin.Signedness { | ||
| 9177 | switch (cc) { | ||
| 9178 | .Unspecified, .Inline, .Async => return null, | ||
| 9179 | else => {}, | ||
| 9180 | } | ||
| 9181 | const int_info = switch (ty.zigTypeTag()) { | ||
| 9182 | .Int, .Enum, .ErrorSet => ty.intInfo(target), | ||
| 9183 | else => return null, | ||
| 9184 | }; | ||
| 9185 | if (int_info.bits <= 16) return int_info.signedness; | ||
| 9186 | switch (target.cpu.arch) { | ||
| 9187 | .sparc64, | ||
| 9188 | .riscv64, | ||
| 9189 | .powerpc64, | ||
| 9190 | .powerpc64le, | ||
| 9191 | => { | ||
| 9192 | if (int_info.bits < 64) { | ||
| 9193 | return int_info.signedness; | ||
| 9194 | } | ||
| 9195 | }, | ||
| 9196 | else => {}, | ||
| 9197 | } | ||
| 9198 | return null; | ||
| 9199 | } | ||
| 9200 | |||
| 9138 | fn isByRef(ty: Type) bool { | 9201 | fn isByRef(ty: Type) bool { |
| 9139 | // For tuples and structs, if there are more than this many non-void | 9202 | // For tuples and structs, if there are more than this many non-void |
| 9140 | // fields, then we make it byref, otherwise byval. | 9203 | // fields, then we make it byref, otherwise byval. |
src/type.zig+10| ... | @@ -4439,6 +4439,16 @@ pub const Type = extern union { | ... | @@ -4439,6 +4439,16 @@ pub const Type = extern union { |
| 4439 | }; | 4439 | }; |
| 4440 | } | 4440 | } |
| 4441 | 4441 | ||
| 4442 | /// Returns true for integers, enums, error sets, and packed structs. | ||
| 4443 | /// If this function returns true, then intInfo() can be called on the type. | ||
| 4444 | pub fn isAbiInt(ty: Type) bool { | ||
| 4445 | return switch (ty.zigTypeTag()) { | ||
| 4446 | .Int, .Enum, .ErrorSet => true, | ||
| 4447 | .Struct => ty.containerLayout() == .Packed, | ||
| 4448 | else => false, | ||
| 4449 | }; | ||
| 4450 | } | ||
| 4451 | |||
| 4442 | /// Asserts the type is an integer, enum, error set, or vector of one of them. | 4452 | /// Asserts the type is an integer, enum, error set, or vector of one of them. |
| 4443 | pub fn intInfo(self: Type, target: Target) struct { signedness: std.builtin.Signedness, bits: u16 } { | 4453 | pub fn intInfo(self: Type, target: Target) struct { signedness: std.builtin.Signedness, bits: u16 } { |
| 4444 | var ty = self; | 4454 | var ty = self; |
src/value.zig+7-10| ... | @@ -1468,8 +1468,7 @@ pub const Value = extern union { | ... | @@ -1468,8 +1468,7 @@ pub const Value = extern union { |
| 1468 | const repr = std.math.break_f80(f); | 1468 | const repr = std.math.break_f80(f); |
| 1469 | std.mem.writeInt(u64, buffer[0..8], repr.fraction, endian); | 1469 | std.mem.writeInt(u64, buffer[0..8], repr.fraction, endian); |
| 1470 | std.mem.writeInt(u16, buffer[8..10], repr.exp, endian); | 1470 | std.mem.writeInt(u16, buffer[8..10], repr.exp, endian); |
| 1471 | // TODO set the rest of the bytes to undefined. should we use 0xaa | 1471 | std.mem.set(u8, buffer[10..], 0); |
| 1472 | // or is there a different way? | ||
| 1473 | return; | 1472 | return; |
| 1474 | } | 1473 | } |
| 1475 | const Int = @Type(.{ .Int = .{ | 1474 | const Int = @Type(.{ .Int = .{ |
| ... | @@ -1481,20 +1480,18 @@ pub const Value = extern union { | ... | @@ -1481,20 +1480,18 @@ pub const Value = extern union { |
| 1481 | } | 1480 | } |
| 1482 | 1481 | ||
| 1483 | fn floatReadFromMemory(comptime F: type, target: Target, buffer: []const u8) F { | 1482 | fn floatReadFromMemory(comptime F: type, target: Target, buffer: []const u8) F { |
| 1483 | const endian = target.cpu.arch.endian(); | ||
| 1484 | if (F == f80) { | 1484 | if (F == f80) { |
| 1485 | switch (target.cpu.arch) { | 1485 | return std.math.make_f80(.{ |
| 1486 | .i386, .x86_64 => return std.math.make_f80(.{ | 1486 | .fraction = readInt(u64, buffer[0..8], endian), |
| 1487 | .fraction = std.mem.readIntLittle(u64, buffer[0..8]), | 1487 | .exp = readInt(u16, buffer[8..10], endian), |
| 1488 | .exp = std.mem.readIntLittle(u16, buffer[8..10]), | 1488 | }); |
| 1489 | }), | ||
| 1490 | else => {}, | ||
| 1491 | } | ||
| 1492 | } | 1489 | } |
| 1493 | const Int = @Type(.{ .Int = .{ | 1490 | const Int = @Type(.{ .Int = .{ |
| 1494 | .signedness = .unsigned, | 1491 | .signedness = .unsigned, |
| 1495 | .bits = @typeInfo(F).Float.bits, | 1492 | .bits = @typeInfo(F).Float.bits, |
| 1496 | } }); | 1493 | } }); |
| 1497 | const int = readInt(Int, buffer[0..@sizeOf(Int)], target.cpu.arch.endian()); | 1494 | const int = readInt(Int, buffer[0..@sizeOf(Int)], endian); |
| 1498 | return @bitCast(F, int); | 1495 | return @bitCast(F, int); |
| 1499 | } | 1496 | } |
| 1500 | 1497 |
test/behavior/math.zig-30| ... | @@ -1168,11 +1168,6 @@ test "remainder division" { | ... | @@ -1168,11 +1168,6 @@ test "remainder division" { |
| 1168 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1168 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1169 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1169 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1170 | 1170 | ||
| 1171 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) { | ||
| 1172 | // https://github.com/ziglang/zig/issues/12054 | ||
| 1173 | return error.SkipZigTest; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | comptime try remdiv(f16); | 1171 | comptime try remdiv(f16); |
| 1177 | comptime try remdiv(f32); | 1172 | comptime try remdiv(f32); |
| 1178 | comptime try remdiv(f64); | 1173 | comptime try remdiv(f64); |
| ... | @@ -1204,11 +1199,6 @@ test "float remainder division using @rem" { | ... | @@ -1204,11 +1199,6 @@ test "float remainder division using @rem" { |
| 1204 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1199 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1205 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1200 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1206 | 1201 | ||
| 1207 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) { | ||
| 1208 | // https://github.com/ziglang/zig/issues/12054 | ||
| 1209 | return error.SkipZigTest; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | comptime try frem(f16); | 1202 | comptime try frem(f16); |
| 1213 | comptime try frem(f32); | 1203 | comptime try frem(f32); |
| 1214 | comptime try frem(f64); | 1204 | comptime try frem(f64); |
| ... | @@ -1251,11 +1241,6 @@ test "float modulo division using @mod" { | ... | @@ -1251,11 +1241,6 @@ test "float modulo division using @mod" { |
| 1251 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1241 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1252 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1242 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1253 | 1243 | ||
| 1254 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) { | ||
| 1255 | // https://github.com/ziglang/zig/issues/12054 | ||
| 1256 | return error.SkipZigTest; | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | comptime try fmod(f16); | 1244 | comptime try fmod(f16); |
| 1260 | comptime try fmod(f32); | 1245 | comptime try fmod(f32); |
| 1261 | comptime try fmod(f64); | 1246 | comptime try fmod(f64); |
| ... | @@ -1431,11 +1416,6 @@ test "@ceil f80" { | ... | @@ -1431,11 +1416,6 @@ test "@ceil f80" { |
| 1431 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1416 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1432 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 1417 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1433 | 1418 | ||
| 1434 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) { | ||
| 1435 | // https://github.com/ziglang/zig/issues/12054 | ||
| 1436 | return error.SkipZigTest; | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | try testCeil(f80, 12.0); | 1419 | try testCeil(f80, 12.0); |
| 1440 | comptime try testCeil(f80, 12.0); | 1420 | comptime try testCeil(f80, 12.0); |
| 1441 | } | 1421 | } |
| ... | @@ -1447,11 +1427,6 @@ test "@ceil f128" { | ... | @@ -1447,11 +1427,6 @@ test "@ceil f128" { |
| 1447 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1427 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1448 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 1428 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1449 | 1429 | ||
| 1450 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) { | ||
| 1451 | // https://github.com/ziglang/zig/issues/12054 | ||
| 1452 | return error.SkipZigTest; | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | try testCeil(f128, 12.0); | 1430 | try testCeil(f128, 12.0); |
| 1456 | comptime try testCeil(f128, 12.0); | 1431 | comptime try testCeil(f128, 12.0); |
| 1457 | } | 1432 | } |
| ... | @@ -1600,11 +1575,6 @@ test "NaN comparison" { | ... | @@ -1600,11 +1575,6 @@ test "NaN comparison" { |
| 1600 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1575 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1601 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1576 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1602 | 1577 | ||
| 1603 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .riscv64) { | ||
| 1604 | // https://github.com/ziglang/zig/issues/12054 | ||
| 1605 | return error.SkipZigTest; | ||
| 1606 | } | ||
| 1607 | |||
| 1608 | try testNanEqNan(f16); | 1578 | try testNanEqNan(f16); |
| 1609 | try testNanEqNan(f32); | 1579 | try testNanEqNan(f32); |
| 1610 | try testNanEqNan(f64); | 1580 | try testNanEqNan(f64); |