Commit daa22d42b0

Vexu <git@vexu.eu>
2019-12-17 10:15:41
translate-c-2 floats
1 parent 9cda93a
Changed files (5)
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<const clang::FloatingLiteral *>(self);
+    return casted->getValueAsApproximateDouble();
+}
+
 enum ZigClangStringLiteral_StringKind ZigClangStringLiteral_getKind(const struct ZigClangStringLiteral *self) {
     auto casted = reinterpret_cast<const clang::StringLiteral *>(self);
     return (ZigClangStringLiteral_StringKind)casted->getKind();
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,
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;
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;
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) {