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) {
633633 if (is_printable(c)) {
634634 fprintf(ar->f, "'%c'", c);
635635 } else {
636 fprintf(ar->f, "'\\x%x'", (int)c);
636 fprintf(ar->f, "'\\x%02x'", (int)c);
637637 }
638638 break;
639639 }
src/ir.cpp+6
......@@ -8113,6 +8113,8 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) {
81138113 case 64:
81148114 dest_val->data.x_f64 = bigfloat_to_f64(bigfloat);
81158115 break;
8116 case 80:
8117 zig_panic("TODO");
81168118 case 128:
81178119 dest_val->data.x_f128 = bigfloat_to_f128(bigfloat);
81188120 break;
......@@ -9974,6 +9976,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
99749976 case 64:
99759977 const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat);
99769978 break;
9979 case 80:
9980 zig_panic("TODO");
99779981 case 128:
99789982 const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat);
99799983 break;
......@@ -10003,6 +10007,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
1000310007 case 64:
1000410008 const_val->data.x_f64 = bigfloat_to_f64(&bigfloat);
1000510009 break;
10010 case 80:
10011 zig_panic("TODO");
1000610012 case 128:
1000710013 const_val->data.x_f128 = bigfloat_to_f128(&bigfloat);
1000810014 break;
src/translate_c.cpp+139-18
......@@ -522,7 +522,18 @@ static AstNode *trans_create_node_apint(Context *c, const ZigClangAPSInt *aps_in
522522 ZigClangAPSInt_getNumWords(negated), true);
523523 ZigClangAPSInt_free(negated);
524524 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;
526537}
527538
528539static const ZigClangType *qual_type_canon(ZigClangQualType qt) {
......@@ -1313,6 +1324,46 @@ static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const
13131324 return maybe_suppress_result(c, result_used, node);
13141325}
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
13161367static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const clang::ConstantExpr *expr) {
13171368 clang::Expr::EvalResult result;
13181369 if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen,
......@@ -1896,15 +1947,21 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra
18961947 case ZigClangCK_ConstructorConversion:
18971948 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ConstructorConversion");
18981949 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;
19051950 case ZigClangCK_PointerToBoolean:
1906 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_PointerToBoolean");
1907 return nullptr;
1951 {
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 }
19081965 case ZigClangCK_ToVoid:
19091966 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ToVoid");
19101967 return nullptr;
......@@ -1912,20 +1969,83 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra
19121969 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_VectorSplat");
19131970 return nullptr;
19141971 case ZigClangCK_IntegralToBoolean:
1915 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToBoolean");
1916 return nullptr;
1972 {
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 }
19172024 case ZigClangCK_IntegralToFloating:
1918 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToFloating");
1919 return nullptr;
2025 case ZigClangCK_FloatingToIntegral:
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 }
19202043 case ZigClangCK_FixedPointCast:
19212044 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointCast");
19222045 return nullptr;
19232046 case ZigClangCK_FixedPointToBoolean:
19242047 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointToBoolean");
19252048 return nullptr;
1926 case ZigClangCK_FloatingToIntegral:
1927 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToIntegral");
1928 return nullptr;
19292049 case ZigClangCK_FloatingToBoolean:
19302050 emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToBoolean");
19312051 return nullptr;
......@@ -3498,7 +3618,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s
34983618 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBridgedCastExprClass");
34993619 return ErrorUnexpected;
35003620 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));
35023623 return ErrorUnexpected;
35033624 case ZigClangStmt_ChooseExprClass:
35043625 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
35373658 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FixedPointLiteralClass");
35383659 return ErrorUnexpected;
35393660 case ZigClangStmt_FloatingLiteralClass:
3540 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FloatingLiteralClass");
3541 return ErrorUnexpected;
3661 return wrap_stmt(out_node, out_child_scope, scope,
3662 trans_floating_literal(c, result_used, (const clang::FloatingLiteral *)stmt));
35423663 case ZigClangStmt_ExprWithCleanupsClass:
35433664 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExprWithCleanupsClass");
35443665 return ErrorUnexpected;
test/translate_c.zig+55
......@@ -1553,6 +1553,61 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15531553 "pub const NOT_ZERO = ~c_uint(0);",
15541554 );
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
15561611 // cases.add("empty array with initializer",
15571612 // "int a[4] = {};"
15581613 // ,