mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
cbe: add support for all float literals types
This commit is contained in:
parent
54326cc554
commit
6021edd7ce
@ -340,7 +340,7 @@ zig_int_operators(64)
|
||||
|
||||
#define zig_int_helpers(w) \
|
||||
static inline zig_i##w zig_shr_i##w(zig_i##w lhs, zig_u8 rhs) { \
|
||||
zig_i##w sign_mask = lhs < zig_as_i##w(0) ? zig_as_i##w(-1) : zig_as_i##w(0); \
|
||||
zig_i##w sign_mask = lhs < zig_as_i##w(0) ? -zig_as_i##w(1) : zig_as_i##w(0); \
|
||||
return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
|
||||
} \
|
||||
\
|
||||
@ -1166,7 +1166,7 @@ static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
|
||||
#define zig_mod_u128 zig_rem_u128
|
||||
|
||||
static inline zig_i128 zig_shr_i128(zig_i128 lhs, zig_u8 rhs) {
|
||||
zig_i128 sign_mask = zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i8(0) ? zig_as_i128(-1, UINT64_MAX) : zig_as_i128(0, 0);
|
||||
zig_i128 sign_mask = zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i8(0) ? -zig_as_i128(0, 1) : zig_as_i128(0, 0);
|
||||
return zig_xor_i128(zig_bitcast_i128(zig_shr_u128(zig_bitcast_u128(zig_xor_i128(lhs, sign_mask)), rhs)), sign_mask);
|
||||
}
|
||||
|
||||
|
||||
@ -415,26 +415,6 @@ pub const Function = struct {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn renderFloatFnName(f: *Function, writer: anytype, operation: []const u8, float_ty: Type) !void {
|
||||
const target = f.object.dg.module.getTarget();
|
||||
const float_bits = float_ty.floatBits(target);
|
||||
const is_longdouble = float_bits == CType.longdouble.sizeInBits(target);
|
||||
try writer.writeAll("__");
|
||||
if (is_longdouble or float_bits != 80) {
|
||||
try writer.writeAll("builtin_");
|
||||
}
|
||||
try writer.writeAll(operation);
|
||||
if (is_longdouble) {
|
||||
try writer.writeByte('l');
|
||||
} else switch (float_bits) {
|
||||
16, 32 => try writer.writeByte('f'),
|
||||
64 => {},
|
||||
80 => try writer.writeByte('x'),
|
||||
128 => try writer.writeByte('q'),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// This data is available when outputting .c code for a `Module`.
|
||||
@ -674,14 +654,18 @@ pub const DeclGen = struct {
|
||||
// bool b = 0xaa; evals to true, but memcpy(&b, 0xaa, 1); evals to false.
|
||||
.Bool => return dg.renderValue(writer, ty, Value.@"false", location),
|
||||
.Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}),
|
||||
.Float => switch (ty.tag()) {
|
||||
.f32 => return writer.print("zig_bitcast_f32_u32({x})", .{
|
||||
try dg.fmtIntLiteral(Type.u32, val),
|
||||
}),
|
||||
.f64 => return writer.print("zig_bitcast_f64_u64({x})", .{
|
||||
try dg.fmtIntLiteral(Type.u64, val),
|
||||
}),
|
||||
else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
|
||||
.Float => {
|
||||
try writer.writeByte('(');
|
||||
try dg.renderTypecast(writer, ty);
|
||||
try writer.writeByte(')');
|
||||
switch (ty.floatBits(target)) {
|
||||
16 => return writer.print("{x}f", .{@bitCast(f16, undefPattern(u16))}),
|
||||
32 => return writer.print("{x}f", .{@bitCast(f32, undefPattern(u32))}),
|
||||
64 => return writer.print("{x}", .{@bitCast(f64, undefPattern(u64))}),
|
||||
80 => return writer.print("{x}l", .{@bitCast(f80, undefPattern(u80))}),
|
||||
128 => return writer.print("{x}l", .{@bitCast(f128, undefPattern(u128))}),
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
.Pointer => switch (ty.ptrSize()) {
|
||||
.Slice => {
|
||||
@ -833,37 +817,41 @@ pub const DeclGen = struct {
|
||||
else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val)}),
|
||||
},
|
||||
.Float => {
|
||||
if (ty.floatBits(target) <= 64) {
|
||||
if (std.math.isNan(val.toFloat(f64)) or std.math.isInf(val.toFloat(f64))) {
|
||||
// just generate a bit cast (exactly like we do in airBitcast)
|
||||
switch (ty.tag()) {
|
||||
.f32 => {
|
||||
var bitcast_pl = Value.Payload.U64{
|
||||
.base = .{ .tag = .int_u64 },
|
||||
.data = @bitCast(u32, val.toFloat(f32)),
|
||||
};
|
||||
const bitcast_val = Value.initPayload(&bitcast_pl.base);
|
||||
return writer.print("zig_bitcast_f32_u32({x})", .{
|
||||
try dg.fmtIntLiteral(Type.u32, bitcast_val),
|
||||
});
|
||||
},
|
||||
.f64 => {
|
||||
var bitcast_pl = Value.Payload.U64{
|
||||
.base = .{ .tag = .int_u64 },
|
||||
.data = @bitCast(u64, val.toFloat(f64)),
|
||||
};
|
||||
const bitcast_val = Value.initPayload(&bitcast_pl.base);
|
||||
return writer.print("zig_bitcast_f64_u64({x})", .{
|
||||
try dg.fmtIntLiteral(Type.u64, bitcast_val),
|
||||
});
|
||||
},
|
||||
else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
|
||||
}
|
||||
} else {
|
||||
return writer.print("{x}", .{val.toFloat(f64)});
|
||||
}
|
||||
try writer.writeByte('(');
|
||||
try dg.renderTypecast(writer, ty);
|
||||
try writer.writeByte(')');
|
||||
const f128_val = val.toFloat(f128);
|
||||
if (!std.math.isFinite(f128_val)) {
|
||||
if (std.math.signbit(f128_val)) try writer.writeByte('-');
|
||||
const fn_name = if (std.math.isSignalNan(f128_val))
|
||||
"nans"
|
||||
else if (std.math.isNan(f128_val))
|
||||
"nan"
|
||||
else if (std.math.isInf(f128_val))
|
||||
"inf"
|
||||
else
|
||||
unreachable;
|
||||
try dg.renderFloatFnName(writer, fn_name, ty);
|
||||
try writer.writeByte('(');
|
||||
if (std.math.isNan(f128_val)) switch (ty.floatBits(target)) {
|
||||
// We only actually need to pass the significant, but it will get
|
||||
// properly masked anyway, so just pass the whole value.
|
||||
16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16))}),
|
||||
32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32))}),
|
||||
64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64))}),
|
||||
80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80))}),
|
||||
128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}),
|
||||
else => unreachable,
|
||||
};
|
||||
return writer.writeByte(')');
|
||||
} else switch (ty.floatBits(target)) {
|
||||
16 => return writer.print("{x}f", .{val.toFloat(f16)}),
|
||||
32 => return writer.print("{x}f", .{val.toFloat(f32)}),
|
||||
64 => return writer.print("{x}", .{val.toFloat(f64)}),
|
||||
80 => return writer.print("{x}l", .{val.toFloat(f80)}),
|
||||
128 => return writer.print("{x}l", .{f128_val}),
|
||||
else => unreachable,
|
||||
}
|
||||
return dg.fail("TODO: C backend: implement lowering large float values", .{});
|
||||
},
|
||||
.Pointer => switch (val.tag()) {
|
||||
.null_value, .zero => {
|
||||
@ -2053,6 +2041,26 @@ pub const DeclGen = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn renderFloatFnName(dg: *DeclGen, writer: anytype, operation: []const u8, float_ty: Type) !void {
|
||||
const target = dg.module.getTarget();
|
||||
const float_bits = float_ty.floatBits(target);
|
||||
const is_longdouble = float_bits == CType.longdouble.sizeInBits(target);
|
||||
try writer.writeAll("__");
|
||||
if (is_longdouble or float_bits != 80) {
|
||||
try writer.writeAll("builtin_");
|
||||
}
|
||||
try writer.writeAll(operation);
|
||||
if (is_longdouble) {
|
||||
try writer.writeByte('l');
|
||||
} else switch (float_bits) {
|
||||
16, 32 => try writer.writeByte('f'),
|
||||
64 => {},
|
||||
80 => try writer.writeByte('x'),
|
||||
128 => try writer.writeByte('q'),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
fn fmtIntLiteral(
|
||||
dg: *DeclGen,
|
||||
ty: Type,
|
||||
@ -5169,7 +5177,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
|
||||
const operand = try f.resolveInst(un_op);
|
||||
const local = try f.allocLocal(inst_ty, .Const);
|
||||
try writer.writeAll(" = ");
|
||||
try f.renderFloatFnName(writer, operation, inst_ty);
|
||||
try f.object.dg.renderFloatFnName(writer, operation, inst_ty);
|
||||
try writer.writeByte('(');
|
||||
try f.writeCValue(writer, operand, .FunctionArgument);
|
||||
try writer.writeAll(");\n");
|
||||
@ -5185,7 +5193,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
|
||||
const rhs = try f.resolveInst(bin_op.rhs);
|
||||
const local = try f.allocLocal(inst_ty, .Const);
|
||||
try writer.writeAll(" = ");
|
||||
try f.renderFloatFnName(writer, operation, inst_ty);
|
||||
try f.object.dg.renderFloatFnName(writer, operation, inst_ty);
|
||||
try writer.writeByte('(');
|
||||
try f.writeCValue(writer, lhs, .FunctionArgument);
|
||||
try writer.writeAll(", ");
|
||||
@ -5205,7 +5213,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const writer = f.object.writer();
|
||||
const local = try f.allocLocal(inst_ty, .Const);
|
||||
try writer.writeAll(" = ");
|
||||
try f.renderFloatFnName(writer, "fma", inst_ty);
|
||||
try f.object.dg.renderFloatFnName(writer, "fma", inst_ty);
|
||||
try writer.writeByte('(');
|
||||
try f.writeCValue(writer, mulend1, .FunctionArgument);
|
||||
try writer.writeAll(", ");
|
||||
@ -5342,6 +5350,10 @@ fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) {
|
||||
return .{ .data = str };
|
||||
}
|
||||
|
||||
fn undefPattern(comptime T: type) T {
|
||||
return (1 << (@bitSizeOf(T) | 1)) / 3;
|
||||
}
|
||||
|
||||
const FormatIntLiteralContext = struct {
|
||||
ty: Type,
|
||||
val: Value,
|
||||
@ -5379,9 +5391,7 @@ fn formatIntLiteral(
|
||||
var int_buf: Value.BigIntSpace = undefined;
|
||||
const int = if (data.val.isUndefDeep()) blk: {
|
||||
undef_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(int_info.bits));
|
||||
|
||||
const undef_pattern: Limb = (1 << (@bitSizeOf(Limb) | 1)) / 3;
|
||||
std.mem.set(Limb, undef_limbs, undef_pattern);
|
||||
std.mem.set(Limb, undef_limbs, undefPattern(Limb));
|
||||
|
||||
var undef_int = BigInt.Mutable{
|
||||
.limbs = undef_limbs,
|
||||
|
||||
@ -8,7 +8,6 @@ test "issue12891" {
|
||||
}
|
||||
test "nan" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
const f = comptime std.math.nan(f64);
|
||||
var i: usize = 0;
|
||||
|
||||
@ -1283,7 +1283,6 @@ fn boolToStr(b: bool) []const u8 {
|
||||
|
||||
test "cast f16 to wider types" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
@ -1302,7 +1301,6 @@ test "cast f16 to wider types" {
|
||||
|
||||
test "cast f128 to narrower types" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
@ -147,7 +147,6 @@ fn testSqrt() !void {
|
||||
|
||||
test "more @sqrt f16 tests" {
|
||||
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_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
@ -608,7 +607,6 @@ test "negation f80" {
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
@ -629,7 +627,6 @@ test "negation f128" {
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
@ -709,7 +706,6 @@ test "nan negation f16" {
|
||||
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
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
const nan_comptime = comptime math.nan(f16);
|
||||
const neg_nan_comptime = -nan_comptime;
|
||||
@ -729,7 +725,6 @@ test "nan negation f32" {
|
||||
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
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
const nan_comptime = comptime math.nan(f32);
|
||||
const neg_nan_comptime = -nan_comptime;
|
||||
@ -749,7 +744,6 @@ test "nan negation f64" {
|
||||
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
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
const nan_comptime = comptime math.nan(f64);
|
||||
const neg_nan_comptime = -nan_comptime;
|
||||
|
||||
@ -1316,7 +1316,6 @@ test "@fabs f80" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) 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
|
||||
|
||||
try testFabs(f80, 12.0);
|
||||
comptime try testFabs(f80, 12.0);
|
||||
@ -1625,7 +1624,6 @@ test "compare undefined literal with comptime_int" {
|
||||
}
|
||||
|
||||
test "signed zeros are represented properly" {
|
||||
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
|
||||
|
||||
@ -44,7 +44,6 @@ fn testMulAdd16() !void {
|
||||
|
||||
test "@mulAdd f80" {
|
||||
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_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
@ -335,7 +335,6 @@ test "pointer sentinel with optional element" {
|
||||
|
||||
test "pointer sentinel with +inf" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
@ -205,7 +205,6 @@ test "initializing anon struct with explicit type" {
|
||||
}
|
||||
|
||||
test "fieldParentPtr of tuple" {
|
||||
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;
|
||||
@ -216,7 +215,6 @@ test "fieldParentPtr of tuple" {
|
||||
}
|
||||
|
||||
test "fieldParentPtr of anon struct" {
|
||||
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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user