authorgravatar for pawalamde@gmail.comzenith391 <pawalamde@gmail.com> 2021-11-10 00:56:01+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-11-09 18:56:01-05:00
log6869bc9ff872b45c4126526eecf9d8607ad73d7a
tree064277ea57b1d130a741722d04454cd1d5142f48
parent0d7359ca9b7e1c88d62ce3ecc6542584fe5df489
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

stage2: Add support for floats in the C backend (#10059)

* Implement float type * Fix int and float undefined value * Handle NaN constants, preserving bit pattern

2 files changed, 63 insertions(+), 7 deletions(-)

src/codegen/c.zig+50-7
...@@ -219,11 +219,36 @@ pub const DeclGen = struct {...@@ -219,11 +219,36 @@ pub const DeclGen = struct {
219 val: Value,219 val: Value,
220 ) error{ OutOfMemory, AnalysisFail }!void {220 ) error{ OutOfMemory, AnalysisFail }!void {
221 if (val.isUndef()) {221 if (val.isUndef()) {
222 // This should lower to 0xaa bytes in safe modes, and for unsafe modes should222 switch (ty.zigTypeTag()) {
223 // lower to leaving variables uninitialized (that might need to be implemented223 // Using '{}' for integer and floats seemed to error C compilers (both GCC and Clang)
224 // outside of this function).224 // with 'error: expected expression' (including when built with 'zig cc')
225 return writer.writeAll("{}");225 .Int => {
226 //return dg.fail("TODO: C backend: implement renderValue undef", .{});226 const c_bits = toCIntBits(ty.intInfo(dg.module.getTarget()).bits) orelse
227 return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
228 switch (c_bits) {
229 8 => return writer.writeAll("0xaaU"),
230 16 => return writer.writeAll("0xaaaaU"),
231 32 => return writer.writeAll("0xaaaaaaaaU"),
232 64 => return writer.writeAll("0xaaaaaaaaaaaaaaaaUL"),
233 128 => return writer.writeAll("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaULL"),
234 else => unreachable,
235 }
236 },
237 .Float => {
238 switch (ty.floatBits(dg.module.getTarget())) {
239 32 => return writer.writeAll("zig_bitcast_f32_u32(0xaaaaaaaa)"),
240 64 => return writer.writeAll("zig_bitcast_f64_u64(0xaaaaaaaaaaaaaaaa)"),
241 else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
242 }
243 },
244
245 else => {
246 // This should lower to 0xaa bytes in safe modes, and for unsafe modes should
247 // lower to leaving variables uninitialized (that might need to be implemented
248 // outside of this function).
249 return writer.writeAll("{}");
250 },
251 }
227 }252 }
228 switch (ty.zigTypeTag()) {253 switch (ty.zigTypeTag()) {
229 .Int => {254 .Int => {
...@@ -233,7 +258,16 @@ pub const DeclGen = struct {...@@ -233,7 +258,16 @@ pub const DeclGen = struct {
233 },258 },
234 .Float => {259 .Float => {
235 if (ty.floatBits(dg.module.getTarget()) <= 64) {260 if (ty.floatBits(dg.module.getTarget()) <= 64) {
236 return writer.print("{x}", .{val.toFloat(f64)});261 if (std.math.isNan(val.toFloat(f64)) or std.math.isInf(val.toFloat(f64))) {
262 // just generate a bit cast (exactly like we do in airBitcast)
263 switch (ty.tag()) {
264 .f32 => return writer.print("zig_bitcast_f32_u32(0x{x})", .{@bitCast(u32, val.toFloat(f32))}),
265 .f64 => return writer.print("zig_bitcast_f64_u64(0x{x})", .{@bitCast(u64, val.toFloat(f64))}),
266 else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
267 }
268 } else {
269 return writer.print("{x}", .{val.toFloat(f64)});
270 }
237 }271 }
238 return dg.fail("TODO: C backend: implement lowering large float values", .{});272 return dg.fail("TODO: C backend: implement lowering large float values", .{});
239 },273 },
...@@ -521,7 +555,16 @@ pub const DeclGen = struct {...@@ -521,7 +555,16 @@ pub const DeclGen = struct {
521 }555 }
522 },556 },
523557
524 .Float => return dg.fail("TODO: C backend: implement type Float", .{}),558 .Float => {
559 switch (t.tag()) {
560 .f32 => try w.writeAll("float"),
561 .f64 => try w.writeAll("double"),
562 .c_longdouble => try w.writeAll("long double"),
563 .f16 => return dg.fail("TODO: C backend: implement float type f16", .{}),
564 .f128 => return dg.fail("TODO: C backend: implement float type f128", .{}),
565 else => unreachable,
566 }
567 },
525568
526 .Pointer => {569 .Pointer => {
527 if (t.isSlice()) {570 if (t.isSlice()) {
src/link/C/zig.h+13
...@@ -123,6 +123,7 @@...@@ -123,6 +123,7 @@
123#include <stdint.h>123#include <stdint.h>
124#include <stddef.h>124#include <stddef.h>
125#include <limits.h>125#include <limits.h>
126
126#define int128_t __int128127#define int128_t __int128
127#define uint128_t unsigned __int128128#define uint128_t unsigned __int128
128ZIG_EXTERN_C void *memcpy (void *ZIG_RESTRICT, const void *ZIG_RESTRICT, size_t);129ZIG_EXTERN_C void *memcpy (void *ZIG_RESTRICT, const void *ZIG_RESTRICT, size_t);
...@@ -356,6 +357,18 @@ static inline long long zig_subw_longlong(long long lhs, long long rhs, long lon...@@ -356,6 +357,18 @@ static inline long long zig_subw_longlong(long long lhs, long long rhs, long lon
356 return (long long)(((unsigned long long)lhs) - ((unsigned long long)rhs));357 return (long long)(((unsigned long long)lhs) - ((unsigned long long)rhs));
357}358}
358359
360static inline float zig_bitcast_f32_u32(uint32_t arg) {
361 float dest;
362 memcpy(&dest, &arg, sizeof dest);
363 return dest;
364}
365
366static inline float zig_bitcast_f64_u64(uint64_t arg) {
367 double dest;
368 memcpy(&dest, &arg, sizeof dest);
369 return dest;
370}
371
359#define zig_add_sat_u(ZT, T) static inline T zig_adds_##ZT(T x, T y, T max) { \372#define zig_add_sat_u(ZT, T) static inline T zig_adds_##ZT(T x, T y, T max) { \
360 return (x > max - y) ? max : x + y; \373 return (x > max - y) ? max : x + y; \
361}374}