From daa22d42b0cdb8ccf04625ea921f3e71b647b68c Mon Sep 17 00:00:00 2001 From: Vexu Date: Tue, 17 Dec 2019 11:15:41 +0200 Subject: [PATCH] translate-c-2 floats --- src-self-hosted/clang.zig | 4 +++ src-self-hosted/translate_c.zig | 60 ++++++++++++++++++++++++++++----- src/zig_clang.cpp | 5 +++ src/zig_clang.h | 1 + test/translate_c.zig | 12 +++++++ 5 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 80d8cd2c06..559a4ad0e5 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -76,6 +76,7 @@ pub const struct_ZigClangFunctionType = @OpaqueType(); pub const struct_ZigClangPredefinedExpr = @OpaqueType(); pub const struct_ZigClangInitListExpr = @OpaqueType(); pub const ZigClangPreprocessingRecord = @OpaqueType(); +pub const ZigClangFloatingLiteral = @OpaqueType(); pub const ZigClangBO = extern enum { PtrMemD, @@ -1051,3 +1052,6 @@ pub extern fn ZigClangForStmt_getInit(*const ZigClangForStmt) ?*const ZigClangSt pub extern fn ZigClangForStmt_getCond(*const ZigClangForStmt) ?*const ZigClangExpr; pub extern fn ZigClangForStmt_getInc(*const ZigClangForStmt) ?*const ZigClangExpr; pub extern fn ZigClangForStmt_getBody(*const ZigClangForStmt) *const ZigClangStmt; + +pub extern fn ZigClangAPFloat_toString(self: *const ZigClangAPFloat, precision: c_uint, maxPadding: c_uint, truncateZero: bool) [*:0]const u8; +pub extern fn ZigClangAPFloat_getValueAsApproximateDouble(*const ZigClangFloatingLiteral) f64; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index cbb7639c42..4cdef9f805 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -632,6 +632,7 @@ fn transStmt( .ContinueStmtClass => return try transCreateNodeContinue(rp.c), .BreakStmtClass => return transBreak(rp, scope), .ForStmtClass => return transForLoop(rp, scope, @ptrCast(*const ZigClangForStmt, stmt)), + .FloatingLiteralClass => return transFloatingLiteral(rp, scope, @ptrCast(*const ZigClangFloatingLiteral, stmt), result_used), else => { return revertAndWarn( rp, @@ -896,16 +897,11 @@ fn transImplicitCastExpr( const sub_expr = ZigClangImplicitCastExpr_getSubExpr(expr); const sub_expr_node = try transExpr(rp, scope, @ptrCast(*const ZigClangExpr, sub_expr), .used, .r_value); switch (ZigClangImplicitCastExpr_getCastKind(expr)) { - .BitCast => { + .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast => { const dest_type = getExprQualType(c, @ptrCast(*const ZigClangExpr, expr)); const src_type = getExprQualType(c, sub_expr); return transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node); }, - .IntegralCast => { - const dest_type = ZigClangExpr_getType(@ptrCast(*const ZigClangExpr, expr)); - const src_type = ZigClangExpr_getType(sub_expr); - return transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node); - }, .FunctionToPointerDecay, .ArrayToPointerDecay => { return maybeSuppressResult(rp, scope, result_used, sub_expr_node); }, @@ -1057,6 +1053,30 @@ fn transCCast( builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); return &builtin_node.base; } + if (cIsFloating(src_type) and cIsFloating(dst_type)) { + const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@floatCast"); + try builtin_node.params.push(try transQualType(rp, dst_type, loc)); + _ = try appendToken(rp.c, .Comma, ","); + try builtin_node.params.push(expr); + builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); + return &builtin_node.base; + } + if (cIsFloating(src_type) and !cIsFloating(dst_type)) { + const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@floatToInt"); + try builtin_node.params.push(try transQualType(rp, dst_type, loc)); + _ = try appendToken(rp.c, .Comma, ","); + try builtin_node.params.push(expr); + builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); + return &builtin_node.base; + } + if (!cIsFloating(src_type) and cIsFloating(dst_type)) { + const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@intToFloat"); + try builtin_node.params.push(try transQualType(rp, dst_type, loc)); + _ = try appendToken(rp.c, .Comma, ","); + try builtin_node.params.push(expr); + builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); + return &builtin_node.base; + } // TODO: maybe widen to increase size // TODO: maybe bitcast to change sign // TODO: maybe truncate to reduce size @@ -1399,6 +1419,16 @@ fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node { return &br.base; } +fn transFloatingLiteral(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangFloatingLiteral, used: ResultUsed) TransError!*ast.Node { + // TODO use something more accurate + const dbl = ZigClangAPFloat_getValueAsApproximateDouble(stmt); + const node = try rp.c.a().create(ast.Node.FloatLiteral); + node.* = .{ + .token = try appendTokenFmt(rp.c, .FloatLiteral, "{d}", .{dbl}), + }; + return maybeSuppressResult(rp, scope, used, &node.base); +} + fn maybeSuppressResult( rp: RestorePoint, scope: *Scope, @@ -1770,6 +1800,20 @@ fn cIsUnsignedInteger(qt: ZigClangQualType) bool { }; } +fn cIsFloating(qt: ZigClangQualType) bool { + const c_type = qualTypeCanon(qt); + if (ZigClangType_getTypeClass(c_type) != .Builtin) return false; + const builtin_ty = @ptrCast(*const ZigClangBuiltinType, c_type); + return switch (ZigClangBuiltinType_getKind(builtin_ty)) { + .Float, + .Double, + .Float128, + .LongDouble, + => true, + else => false, + }; +} + fn transCreateNodeAssign( rp: RestorePoint, scope: *Scope, @@ -1964,7 +2008,7 @@ fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node { }; const token = try appendToken(c, .IntegerLiteral, str); const node = try c.a().create(ast.Node.IntegerLiteral); - node.* = ast.Node.IntegerLiteral{ + node.* = .{ .token = token, }; return &node.base; @@ -2027,7 +2071,7 @@ fn transCreateNodeArrayInitializer(c: *Context, dot_tok: ast.TokenIndex) !*ast.N fn transCreateNodeInt(c: *Context, int: var) !*ast.Node { const token = try appendTokenFmt(c, .IntegerLiteral, "{}", .{int}); const node = try c.a().create(ast.Node.IntegerLiteral); - node.* = ast.Node.IntegerLiteral{ + node.* = .{ .token = token, }; return &node.base; diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 86ef17ffbe..d87b769f5e 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -2161,6 +2161,11 @@ unsigned ZigClangAPFloat_convertToHexString(const ZigClangAPFloat *self, char *D return casted->convertToHexString(DST, HexDigits, UpperCase, (llvm::APFloat::roundingMode)RM); } +double ZigClangAPFloat_getValueAsApproximateDouble(const ZigClangFloatingLiteral *self) { + auto casted = reinterpret_cast(self); + return casted->getValueAsApproximateDouble(); +} + enum ZigClangStringLiteral_StringKind ZigClangStringLiteral_getKind(const struct ZigClangStringLiteral *self) { auto casted = reinterpret_cast(self); return (ZigClangStringLiteral_StringKind)casted->getKind(); diff --git a/src/zig_clang.h b/src/zig_clang.h index cf60fdfca9..8dd0b9b3d5 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -985,6 +985,7 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangDeclStmt_getBeginLoc(const st ZIG_EXTERN_C unsigned ZigClangAPFloat_convertToHexString(const struct ZigClangAPFloat *self, char *DST, unsigned HexDigits, bool UpperCase, enum ZigClangAPFloat_roundingMode RM); +ZIG_EXTERN_C double ZigClangAPFloat_getValueAsApproximateDouble(const ZigClangFloatingLiteral *self); ZIG_EXTERN_C enum ZigClangStringLiteral_StringKind ZigClangStringLiteral_getKind(const struct ZigClangStringLiteral *self); ZIG_EXTERN_C const char *ZigClangStringLiteral_getString_bytes_begin_size(const struct ZigClangStringLiteral *self, diff --git a/test/translate_c.zig b/test/translate_c.zig index 93535987d5..02ba62a471 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -825,6 +825,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub export var _anyerror: c_uint = @as(c_uint, 2); }); + cases.add_2("floats", + \\float a = 3.1415; + \\double b = 3.1415; + \\int c = 3.1415; + \\double d = 3; + , &[_][]const u8{ + \\pub export var a: f32 = @floatCast(f32, 3.1415); + \\pub export var b: f64 = 3.1415; + \\pub export var c: c_int = @floatToInt(c_int, 3.1415); + \\pub export var d: f64 = @intToFloat(f64, 3); + }); + /////////////// Cases for only stage1 which are TODO items for stage2 //////////////// if (builtin.os != builtin.Os.windows) {