Skip to content

Commit

Permalink
C backend: better f16 support
Browse files Browse the repository at this point in the history
  • Loading branch information
jean-dao committed Mar 16, 2022
1 parent 7864e71 commit 8baf976
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 6 deletions.
11 changes: 5 additions & 6 deletions src/codegen/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,6 @@ pub const DeclGen = struct {
}

fn renderSmallFloat(
dg: *DeclGen,
comptime T: type,
writer: anytype,
val: Value,
Expand All @@ -534,7 +533,7 @@ pub const DeclGen = struct {
if (std.math.isNan(v) or std.math.isInf(v)) {
// just generate a bit cast (exactly like we do in airBitcast)
switch (T) {
f16 => return dg.fail("TODO: C backend: implement 16-bit float lowering", .{}),
f16 => return writer.print("zig_bitcast_f16_u16(0x{x})", .{v}),
f32 => return writer.print("zig_bitcast_f32_u32(0x{x})", .{v}),
f64 => return writer.print("zig_bitcast_f64_u64(0x{x})", .{v}),
else => unreachable,
Expand Down Expand Up @@ -607,9 +606,9 @@ pub const DeclGen = struct {
},
.Float => {
switch (ty.tag()) {
.f16 => return dg.renderSmallFloat(f16, writer, val),
.f32 => return dg.renderSmallFloat(f32, writer, val),
.f64 => return dg.renderSmallFloat(f64, writer, val),
.f16 => return renderSmallFloat(f16, writer, val),
.f32 => return renderSmallFloat(f32, writer, val),
.f64 => return renderSmallFloat(f64, writer, val),
.f128 => return renderFloat128(writer, val.toFloat(f128)),
else => unreachable,
}
Expand Down Expand Up @@ -1241,7 +1240,7 @@ pub const DeclGen = struct {
.f32 => try w.writeAll("float"),
.f64 => try w.writeAll("double"),
.c_longdouble => try w.writeAll("long double"),
.f16 => return dg.fail("TODO: C backend: implement float type f16", .{}),
.f16 => try w.writeAll("float16_t"),
.f128 => try w.writeAll("float128_t"),
else => unreachable,
}
Expand Down
21 changes: 21 additions & 0 deletions src/link/C/zig.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,19 @@
#define float128_t __float128
#endif

#if defined(__clang__)
#define ZIG_HAS_FLOAT16
#define float16_t __fp16
#elif defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))
#define ZIG_HAS_FLOAT16
#define float16_t __fp16
#elif defined(__GNUC__) && defined(__i386__) && defined(__SSE2__)
#define ZIG_HAS_FLOAT16
#define float16_t _Float16
#else
#define float16_t float16_t_is_not_supported_on_this_target
#endif

ZIG_EXTERN_C void *memcpy (void *ZIG_RESTRICT, const void *ZIG_RESTRICT, size_t);
ZIG_EXTERN_C void *memset (void *, int, size_t);

Expand Down Expand Up @@ -405,6 +418,14 @@ static inline long long zig_subw_longlong(long long lhs, long long rhs, long lon
return (long long)(((unsigned long long)lhs) - ((unsigned long long)rhs));
}

#if defined(ZIG_HAS_FLOAT16)
static inline float zig_bitcast_f16_u16(uint16_t arg) {
float16_t dest;
memcpy(&dest, &arg, sizeof dest);
return dest;
}
#endif

static inline float zig_bitcast_f32_u32(uint32_t arg) {
float dest;
memcpy(&dest, &arg, sizeof dest);
Expand Down
11 changes: 11 additions & 0 deletions test/behavior/floatop.zig
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,17 @@ test "f128 at compile time is lossy" {
try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
}

test "f16 literals" {
var buf: f16 = math.f16_min;
try expect(math.f16_min == buf);

buf = math.f16_max;
try expect(math.f16_max == buf);

buf = 0;
try expect(@as(f16, 0) == buf);
}

test "f128 tests" {
if (builtin.zig_backend != .stage2_c) return error.SkipZigTest; // TODO

Expand Down

0 comments on commit 8baf976

Please sign in to comment.