Skip to content

Commit ad994c9

Browse files
authored
Merge pull request #2296 from LemonBoy/translate-c-stuff
Handle implicit casts in translate-c
2 parents 7bafe2e + 70c2e86 commit ad994c9

File tree

4 files changed

+201
-19
lines changed

4 files changed

+201
-19
lines changed

src/ast_render.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 139 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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

527+
static 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

528539
static 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

1327+
static 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+
1337+
static 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+
13161367
static 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,36 +1947,105 @@ 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;
19111968
case ZigClangCK_VectorSplat:
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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
// ,

0 commit comments

Comments
 (0)