authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-24 14:43:46-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-04-24 14:43:46-04:00
logad994c96423dd1fcf81d3069aa2d39e345a0aeba
treee1a4514018fdd60fd496291a4382e9d2e6a2c8b7
parent7bafe2e490576f8b6f401ed4e9cedfa9fb395127
parent70c2e86da36abdd56fd61b77682643129fcf6371
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #2296 from LemonBoy/translate-c-stuff

Handle implicit casts in translate-c

4 files changed, 201 insertions(+), 19 deletions(-)

src/ast_render.cpp+1-1
...@@ -633,7 +633,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -633,7 +633,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
633 if (is_printable(c)) {633 if (is_printable(c)) {
634 fprintf(ar->f, "'%c'", c);634 fprintf(ar->f, "'%c'", c);
635 } else {635 } else {
636 fprintf(ar->f, "'\\x%x'", (int)c);636 fprintf(ar->f, "'\\x%02x'", (int)c);
637 }637 }
638 break;638 break;
639 }639 }
src/ir.cpp+6
...@@ -8113,6 +8113,8 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) {...@@ -8113,6 +8113,8 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) {
8113 case 64:8113 case 64:
8114 dest_val->data.x_f64 = bigfloat_to_f64(bigfloat);8114 dest_val->data.x_f64 = bigfloat_to_f64(bigfloat);
8115 break;8115 break;
8116 case 80:
8117 zig_panic("TODO");
8116 case 128:8118 case 128:
8117 dest_val->data.x_f128 = bigfloat_to_f128(bigfloat);8119 dest_val->data.x_f128 = bigfloat_to_f128(bigfloat);
8118 break;8120 break;
...@@ -9974,6 +9976,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -9974,6 +9976,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
9974 case 64:9976 case 64:
9975 const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat);9977 const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat);
9976 break;9978 break;
9979 case 80:
9980 zig_panic("TODO");
9977 case 128:9981 case 128:
9978 const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat);9982 const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat);
9979 break;9983 break;
...@@ -10003,6 +10007,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -10003,6 +10007,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
10003 case 64:10007 case 64:
10004 const_val->data.x_f64 = bigfloat_to_f64(&bigfloat);10008 const_val->data.x_f64 = bigfloat_to_f64(&bigfloat);
10005 break;10009 break;
10010 case 80:
10011 zig_panic("TODO");
10006 case 128:10012 case 128:
10007 const_val->data.x_f128 = bigfloat_to_f128(&bigfloat);10013 const_val->data.x_f128 = bigfloat_to_f128(&bigfloat);
10008 break;10014 break;
src/translate_c.cpp+139-18
...@@ -522,7 +522,18 @@ static AstNode *trans_create_node_apint(Context *c, const ZigClangAPSInt *aps_in...@@ -522,7 +522,18 @@ static AstNode *trans_create_node_apint(Context *c, const ZigClangAPSInt *aps_in
522 ZigClangAPSInt_getNumWords(negated), true);522 ZigClangAPSInt_getNumWords(negated), true);
523 ZigClangAPSInt_free(negated);523 ZigClangAPSInt_free(negated);
524 return node;524 return node;
525}
525526
527static AstNode *trans_create_node_apfloat(Context *c, const llvm::APFloat &ap_float) {
528 uint8_t buf[128];
529 size_t written = ap_float.convertToHexString((char *)buf, 0, false,
530 llvm::APFloat::rmNearestTiesToEven);
531 AstNode *node = trans_create_node(c, NodeTypeFloatLiteral);
532 node->data.float_literal.bigfloat = allocate<BigFloat>(1);
533 if (bigfloat_init_buf(node->data.float_literal.bigfloat, buf, written)) {
534 node->data.float_literal.overflow = true;
535 }
536 return node;
526}537}
527538
528static const ZigClangType *qual_type_canon(ZigClangQualType qt) {539static const ZigClangType *qual_type_canon(ZigClangQualType qt) {
...@@ -1313,6 +1324,46 @@ static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const...@@ -1313,6 +1324,46 @@ static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const
1313 return maybe_suppress_result(c, result_used, node);1324 return maybe_suppress_result(c, result_used, node);
1314}1325}
13151326
1327static AstNode *trans_floating_literal(Context *c, ResultUsed result_used, const clang::FloatingLiteral *stmt) {
1328 llvm::APFloat result{0.0f};
1329 if (!stmt->EvaluateAsFloat(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
1330 emit_warning(c, bitcast(stmt->getBeginLoc()), "invalid floating literal");
1331 return nullptr;
1332 }
1333 AstNode *node = trans_create_node_apfloat(c, result);
1334 return maybe_suppress_result(c, result_used, node);
1335}
1336
1337static AstNode *trans_character_literal(Context *c, ResultUsed result_used, const clang::CharacterLiteral *stmt) {
1338 switch (stmt->getKind()) {
1339 case clang::CharacterLiteral::CharacterKind::Ascii:
1340 {
1341 unsigned val = stmt->getValue();
1342 // C has a somewhat obscure feature called multi-character character
1343 // constant
1344 if (val > 255)
1345 return trans_create_node_unsigned(c, val);
1346 }
1347 // fallthrough
1348 case clang::CharacterLiteral::CharacterKind::UTF8:
1349 {
1350 AstNode *node = trans_create_node(c, NodeTypeCharLiteral);
1351 node->data.char_literal.value = stmt->getValue();
1352 return maybe_suppress_result(c, result_used, node);
1353 }
1354 case clang::CharacterLiteral::CharacterKind::UTF16:
1355 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF16 character literals");
1356 return nullptr;
1357 case clang::CharacterLiteral::CharacterKind::UTF32:
1358 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF32 character literals");
1359 return nullptr;
1360 case clang::CharacterLiteral::CharacterKind::Wide:
1361 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support wide character literals");
1362 return nullptr;
1363 }
1364 zig_unreachable();
1365}
1366
1316static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const clang::ConstantExpr *expr) {1367static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const clang::ConstantExpr *expr) {
1317 clang::Expr::EvalResult result;1368 clang::Expr::EvalResult result;
1318 if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen,1369 if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen,
...@@ -1896,15 +1947,21 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra...@@ -1896,15 +1947,21 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra
1896 case ZigClangCK_ConstructorConversion:1947 case ZigClangCK_ConstructorConversion:
1897 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ConstructorConversion");1948 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ConstructorConversion");
1898 return nullptr;1949 return nullptr;
1899 case ZigClangCK_IntegralToPointer:
1900 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToPointer");
1901 return nullptr;
1902 case ZigClangCK_PointerToIntegral:
1903 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_PointerToIntegral");
1904 return nullptr;
1905 case ZigClangCK_PointerToBoolean:1950 case ZigClangCK_PointerToBoolean:
1906 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_PointerToBoolean");1951 {
1907 return nullptr;1952 const clang::Expr *expr = stmt->getSubExpr();
1953 AstNode *val = trans_expr(c, ResultUsedYes, scope, bitcast(expr), TransRValue);
1954 if (val == nullptr)
1955 return nullptr;
1956
1957 AstNode *val_ptr = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
1958 val_ptr->data.fn_call_expr.params.append(val);
1959
1960 AstNode *zero = trans_create_node_unsigned(c, 0);
1961
1962 // Translate as @ptrToInt((&val) != 0)
1963 return trans_create_node_bin_op(c, val_ptr, BinOpTypeCmpNotEq, zero);
1964 }
1908 case ZigClangCK_ToVoid:1965 case ZigClangCK_ToVoid:
1909 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ToVoid");1966 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ToVoid");
1910 return nullptr;1967 return nullptr;
...@@ -1912,20 +1969,83 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra...@@ -1912,20 +1969,83 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra
1912 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_VectorSplat");1969 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_VectorSplat");
1913 return nullptr;1970 return nullptr;
1914 case ZigClangCK_IntegralToBoolean:1971 case ZigClangCK_IntegralToBoolean:
1915 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToBoolean");1972 {
1916 return nullptr;1973 const clang::Expr *expr = stmt->getSubExpr();
1974
1975 bool expr_val;
1976 if (expr->EvaluateAsBooleanCondition(expr_val, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
1977 return trans_create_node_bool(c, expr_val);
1978 }
1979
1980 AstNode *val = trans_expr(c, ResultUsedYes, scope, bitcast(expr), TransRValue);
1981 if (val == nullptr)
1982 return nullptr;
1983
1984 AstNode *zero = trans_create_node_unsigned(c, 0);
1985
1986 // Translate as val != 0
1987 return trans_create_node_bin_op(c, val, BinOpTypeCmpNotEq, zero);
1988 }
1989 case ZigClangCK_PointerToIntegral:
1990 {
1991 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
1992 if (target_node == nullptr)
1993 return nullptr;
1994
1995 AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
1996 if (dest_type_node == nullptr)
1997 return nullptr;
1998
1999 AstNode *val_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
2000 val_node->data.fn_call_expr.params.append(target_node);
2001 // @ptrToInt always returns a usize
2002 AstNode *node = trans_create_node_builtin_fn_call_str(c, "intCast");
2003 node->data.fn_call_expr.params.append(dest_type_node);
2004 node->data.fn_call_expr.params.append(val_node);
2005
2006 return maybe_suppress_result(c, result_used, node);
2007 }
2008 case ZigClangCK_IntegralToPointer:
2009 {
2010 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
2011 if (target_node == nullptr)
2012 return nullptr;
2013
2014 AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
2015 if (dest_type_node == nullptr)
2016 return nullptr;
2017
2018 AstNode *node = trans_create_node_builtin_fn_call_str(c, "intToPtr");
2019 node->data.fn_call_expr.params.append(dest_type_node);
2020 node->data.fn_call_expr.params.append(target_node);
2021
2022 return maybe_suppress_result(c, result_used, node);
2023 }
1917 case ZigClangCK_IntegralToFloating:2024 case ZigClangCK_IntegralToFloating:
1918 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToFloating");2025 case ZigClangCK_FloatingToIntegral:
1919 return nullptr;2026 {
2027 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
2028 if (target_node == nullptr)
2029 return nullptr;
2030
2031 AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
2032 if (dest_type_node == nullptr)
2033 return nullptr;
2034
2035 char const *fn = (ZigClangCK)stmt->getCastKind() == ZigClangCK_IntegralToFloating ?
2036 "intToFloat" : "floatToInt";
2037 AstNode *node = trans_create_node_builtin_fn_call_str(c, fn);
2038 node->data.fn_call_expr.params.append(dest_type_node);
2039 node->data.fn_call_expr.params.append(target_node);
2040
2041 return maybe_suppress_result(c, result_used, node);
2042 }
1920 case ZigClangCK_FixedPointCast:2043 case ZigClangCK_FixedPointCast:
1921 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointCast");2044 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointCast");
1922 return nullptr;2045 return nullptr;
1923 case ZigClangCK_FixedPointToBoolean:2046 case ZigClangCK_FixedPointToBoolean:
1924 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointToBoolean");2047 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointToBoolean");
1925 return nullptr;2048 return nullptr;
1926 case ZigClangCK_FloatingToIntegral:
1927 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToIntegral");
1928 return nullptr;
1929 case ZigClangCK_FloatingToBoolean:2049 case ZigClangCK_FloatingToBoolean:
1930 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToBoolean");2050 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToBoolean");
1931 return nullptr;2051 return nullptr;
...@@ -3498,7 +3618,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s...@@ -3498,7 +3618,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s
3498 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBridgedCastExprClass");3618 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBridgedCastExprClass");
3499 return ErrorUnexpected;3619 return ErrorUnexpected;
3500 case ZigClangStmt_CharacterLiteralClass:3620 case ZigClangStmt_CharacterLiteralClass:
3501 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CharacterLiteralClass");3621 return wrap_stmt(out_node, out_child_scope, scope,
3622 trans_character_literal(c, result_used, (const clang::CharacterLiteral *)stmt));
3502 return ErrorUnexpected;3623 return ErrorUnexpected;
3503 case ZigClangStmt_ChooseExprClass:3624 case ZigClangStmt_ChooseExprClass:
3504 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ChooseExprClass");3625 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ChooseExprClass");
...@@ -3537,8 +3658,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s...@@ -3537,8 +3658,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s
3537 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FixedPointLiteralClass");3658 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FixedPointLiteralClass");
3538 return ErrorUnexpected;3659 return ErrorUnexpected;
3539 case ZigClangStmt_FloatingLiteralClass:3660 case ZigClangStmt_FloatingLiteralClass:
3540 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FloatingLiteralClass");3661 return wrap_stmt(out_node, out_child_scope, scope,
3541 return ErrorUnexpected;3662 trans_floating_literal(c, result_used, (const clang::FloatingLiteral *)stmt));
3542 case ZigClangStmt_ExprWithCleanupsClass:3663 case ZigClangStmt_ExprWithCleanupsClass:
3543 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExprWithCleanupsClass");3664 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExprWithCleanupsClass");
3544 return ErrorUnexpected;3665 return ErrorUnexpected;
test/translate_c.zig+55
...@@ -1553,6 +1553,61 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1553,6 +1553,61 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1553 "pub const NOT_ZERO = ~c_uint(0);",1553 "pub const NOT_ZERO = ~c_uint(0);",
1554 );1554 );
15551555
1556 cases.addC("implicit casts",
1557 \\#include <stdbool.h>
1558 \\
1559 \\void fn_int(int x);
1560 \\void fn_f32(float x);
1561 \\void fn_f64(double x);
1562 \\void fn_char(char x);
1563 \\void fn_bool(bool x);
1564 \\void fn_ptr(void *x);
1565 \\
1566 \\void call(int q) {
1567 \\ fn_int(3.0f);
1568 \\ fn_int(3.0);
1569 \\ fn_int(3.0L);
1570 \\ fn_int('ABCD');
1571 \\ fn_f32(3);
1572 \\ fn_f64(3);
1573 \\ fn_char('3');
1574 \\ fn_char('\x1');
1575 \\ fn_char(0);
1576 \\ fn_f32(3.0f);
1577 \\ fn_f64(3.0);
1578 \\ fn_bool(123);
1579 \\ fn_bool(0);
1580 \\ fn_bool(&fn_int);
1581 \\ fn_int(&fn_int);
1582 \\ fn_ptr(42);
1583 \\}
1584 ,
1585 \\pub extern fn fn_int(x: c_int) void;
1586 \\pub extern fn fn_f32(x: f32) void;
1587 \\pub extern fn fn_f64(x: f64) void;
1588 \\pub extern fn fn_char(x: u8) void;
1589 \\pub extern fn fn_bool(x: bool) void;
1590 \\pub extern fn fn_ptr(x: ?*c_void) void;
1591 \\pub export fn call(q: c_int) void {
1592 \\ fn_int(@floatToInt(c_int, 3.000000));
1593 \\ fn_int(@floatToInt(c_int, 3.000000));
1594 \\ fn_int(@floatToInt(c_int, 3.000000));
1595 \\ fn_int(1094861636);
1596 \\ fn_f32(@intToFloat(f32, 3));
1597 \\ fn_f64(@intToFloat(f64, 3));
1598 \\ fn_char(u8('3'));
1599 \\ fn_char(u8('\x01'));
1600 \\ fn_char(u8(0));
1601 \\ fn_f32(3.000000);
1602 \\ fn_f64(3.000000);
1603 \\ fn_bool(true);
1604 \\ fn_bool(false);
1605 \\ fn_bool(@ptrToInt(&fn_int) != 0);
1606 \\ fn_int(@intCast(c_int, @ptrToInt(&fn_int)));
1607 \\ fn_ptr(@intToPtr(?*c_void, 42));
1608 \\}
1609 );
1610
1556 // cases.add("empty array with initializer",1611 // cases.add("empty array with initializer",
1557 // "int a[4] = {};"1612 // "int a[4] = {};"
1558 // ,1613 // ,