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

Handle implicit casts in translate-c
This commit is contained in:
Andrew Kelley 2019-04-24 14:43:46 -04:00 committed by GitHub
commit ad994c9642
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 201 additions and 19 deletions

View File

@ -633,7 +633,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
if (is_printable(c)) {
fprintf(ar->f, "'%c'", c);
} else {
fprintf(ar->f, "'\\x%x'", (int)c);
fprintf(ar->f, "'\\x%02x'", (int)c);
}
break;
}

View File

@ -8113,6 +8113,8 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) {
case 64:
dest_val->data.x_f64 = bigfloat_to_f64(bigfloat);
break;
case 80:
zig_panic("TODO");
case 128:
dest_val->data.x_f128 = bigfloat_to_f128(bigfloat);
break;
@ -9974,6 +9976,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
case 64:
const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat);
break;
case 80:
zig_panic("TODO");
case 128:
const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat);
break;
@ -10003,6 +10007,8 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
case 64:
const_val->data.x_f64 = bigfloat_to_f64(&bigfloat);
break;
case 80:
zig_panic("TODO");
case 128:
const_val->data.x_f128 = bigfloat_to_f128(&bigfloat);
break;

View File

@ -522,7 +522,18 @@ static AstNode *trans_create_node_apint(Context *c, const ZigClangAPSInt *aps_in
ZigClangAPSInt_getNumWords(negated), true);
ZigClangAPSInt_free(negated);
return node;
}
static AstNode *trans_create_node_apfloat(Context *c, const llvm::APFloat &ap_float) {
uint8_t buf[128];
size_t written = ap_float.convertToHexString((char *)buf, 0, false,
llvm::APFloat::rmNearestTiesToEven);
AstNode *node = trans_create_node(c, NodeTypeFloatLiteral);
node->data.float_literal.bigfloat = allocate<BigFloat>(1);
if (bigfloat_init_buf(node->data.float_literal.bigfloat, buf, written)) {
node->data.float_literal.overflow = true;
}
return node;
}
static const ZigClangType *qual_type_canon(ZigClangQualType qt) {
@ -1313,6 +1324,46 @@ static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const
return maybe_suppress_result(c, result_used, node);
}
static AstNode *trans_floating_literal(Context *c, ResultUsed result_used, const clang::FloatingLiteral *stmt) {
llvm::APFloat result{0.0f};
if (!stmt->EvaluateAsFloat(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
emit_warning(c, bitcast(stmt->getBeginLoc()), "invalid floating literal");
return nullptr;
}
AstNode *node = trans_create_node_apfloat(c, result);
return maybe_suppress_result(c, result_used, node);
}
static AstNode *trans_character_literal(Context *c, ResultUsed result_used, const clang::CharacterLiteral *stmt) {
switch (stmt->getKind()) {
case clang::CharacterLiteral::CharacterKind::Ascii:
{
unsigned val = stmt->getValue();
// C has a somewhat obscure feature called multi-character character
// constant
if (val > 255)
return trans_create_node_unsigned(c, val);
}
// fallthrough
case clang::CharacterLiteral::CharacterKind::UTF8:
{
AstNode *node = trans_create_node(c, NodeTypeCharLiteral);
node->data.char_literal.value = stmt->getValue();
return maybe_suppress_result(c, result_used, node);
}
case clang::CharacterLiteral::CharacterKind::UTF16:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF16 character literals");
return nullptr;
case clang::CharacterLiteral::CharacterKind::UTF32:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF32 character literals");
return nullptr;
case clang::CharacterLiteral::CharacterKind::Wide:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support wide character literals");
return nullptr;
}
zig_unreachable();
}
static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const clang::ConstantExpr *expr) {
clang::Expr::EvalResult result;
if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen,
@ -1896,15 +1947,21 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra
case ZigClangCK_ConstructorConversion:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ConstructorConversion");
return nullptr;
case ZigClangCK_IntegralToPointer:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToPointer");
return nullptr;
case ZigClangCK_PointerToIntegral:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_PointerToIntegral");
return nullptr;
case ZigClangCK_PointerToBoolean:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_PointerToBoolean");
return nullptr;
{
const clang::Expr *expr = stmt->getSubExpr();
AstNode *val = trans_expr(c, ResultUsedYes, scope, bitcast(expr), TransRValue);
if (val == nullptr)
return nullptr;
AstNode *val_ptr = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
val_ptr->data.fn_call_expr.params.append(val);
AstNode *zero = trans_create_node_unsigned(c, 0);
// Translate as @ptrToInt((&val) != 0)
return trans_create_node_bin_op(c, val_ptr, BinOpTypeCmpNotEq, zero);
}
case ZigClangCK_ToVoid:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ToVoid");
return nullptr;
@ -1912,20 +1969,83 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_VectorSplat");
return nullptr;
case ZigClangCK_IntegralToBoolean:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToBoolean");
return nullptr;
{
const clang::Expr *expr = stmt->getSubExpr();
bool expr_val;
if (expr->EvaluateAsBooleanCondition(expr_val, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
return trans_create_node_bool(c, expr_val);
}
AstNode *val = trans_expr(c, ResultUsedYes, scope, bitcast(expr), TransRValue);
if (val == nullptr)
return nullptr;
AstNode *zero = trans_create_node_unsigned(c, 0);
// Translate as val != 0
return trans_create_node_bin_op(c, val, BinOpTypeCmpNotEq, zero);
}
case ZigClangCK_PointerToIntegral:
{
AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
if (target_node == nullptr)
return nullptr;
AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
if (dest_type_node == nullptr)
return nullptr;
AstNode *val_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
val_node->data.fn_call_expr.params.append(target_node);
// @ptrToInt always returns a usize
AstNode *node = trans_create_node_builtin_fn_call_str(c, "intCast");
node->data.fn_call_expr.params.append(dest_type_node);
node->data.fn_call_expr.params.append(val_node);
return maybe_suppress_result(c, result_used, node);
}
case ZigClangCK_IntegralToPointer:
{
AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
if (target_node == nullptr)
return nullptr;
AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
if (dest_type_node == nullptr)
return nullptr;
AstNode *node = trans_create_node_builtin_fn_call_str(c, "intToPtr");
node->data.fn_call_expr.params.append(dest_type_node);
node->data.fn_call_expr.params.append(target_node);
return maybe_suppress_result(c, result_used, node);
}
case ZigClangCK_IntegralToFloating:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToFloating");
return nullptr;
case ZigClangCK_FloatingToIntegral:
{
AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue);
if (target_node == nullptr)
return nullptr;
AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
if (dest_type_node == nullptr)
return nullptr;
char const *fn = (ZigClangCK)stmt->getCastKind() == ZigClangCK_IntegralToFloating ?
"intToFloat" : "floatToInt";
AstNode *node = trans_create_node_builtin_fn_call_str(c, fn);
node->data.fn_call_expr.params.append(dest_type_node);
node->data.fn_call_expr.params.append(target_node);
return maybe_suppress_result(c, result_used, node);
}
case ZigClangCK_FixedPointCast:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointCast");
return nullptr;
case ZigClangCK_FixedPointToBoolean:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointToBoolean");
return nullptr;
case ZigClangCK_FloatingToIntegral:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToIntegral");
return nullptr;
case ZigClangCK_FloatingToBoolean:
emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToBoolean");
return nullptr;
@ -3498,7 +3618,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s
emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBridgedCastExprClass");
return ErrorUnexpected;
case ZigClangStmt_CharacterLiteralClass:
emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CharacterLiteralClass");
return wrap_stmt(out_node, out_child_scope, scope,
trans_character_literal(c, result_used, (const clang::CharacterLiteral *)stmt));
return ErrorUnexpected;
case ZigClangStmt_ChooseExprClass:
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
emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FixedPointLiteralClass");
return ErrorUnexpected;
case ZigClangStmt_FloatingLiteralClass:
emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FloatingLiteralClass");
return ErrorUnexpected;
return wrap_stmt(out_node, out_child_scope, scope,
trans_floating_literal(c, result_used, (const clang::FloatingLiteral *)stmt));
case ZigClangStmt_ExprWithCleanupsClass:
emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExprWithCleanupsClass");
return ErrorUnexpected;

View File

@ -1553,6 +1553,61 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
"pub const NOT_ZERO = ~c_uint(0);",
);
cases.addC("implicit casts",
\\#include <stdbool.h>
\\
\\void fn_int(int x);
\\void fn_f32(float x);
\\void fn_f64(double x);
\\void fn_char(char x);
\\void fn_bool(bool x);
\\void fn_ptr(void *x);
\\
\\void call(int q) {
\\ fn_int(3.0f);
\\ fn_int(3.0);
\\ fn_int(3.0L);
\\ fn_int('ABCD');
\\ fn_f32(3);
\\ fn_f64(3);
\\ fn_char('3');
\\ fn_char('\x1');
\\ fn_char(0);
\\ fn_f32(3.0f);
\\ fn_f64(3.0);
\\ fn_bool(123);
\\ fn_bool(0);
\\ fn_bool(&fn_int);
\\ fn_int(&fn_int);
\\ fn_ptr(42);
\\}
,
\\pub extern fn fn_int(x: c_int) void;
\\pub extern fn fn_f32(x: f32) void;
\\pub extern fn fn_f64(x: f64) void;
\\pub extern fn fn_char(x: u8) void;
\\pub extern fn fn_bool(x: bool) void;
\\pub extern fn fn_ptr(x: ?*c_void) void;
\\pub export fn call(q: c_int) void {
\\ fn_int(@floatToInt(c_int, 3.000000));
\\ fn_int(@floatToInt(c_int, 3.000000));
\\ fn_int(@floatToInt(c_int, 3.000000));
\\ fn_int(1094861636);
\\ fn_f32(@intToFloat(f32, 3));
\\ fn_f64(@intToFloat(f64, 3));
\\ fn_char(u8('3'));
\\ fn_char(u8('\x01'));
\\ fn_char(u8(0));
\\ fn_f32(3.000000);
\\ fn_f64(3.000000);
\\ fn_bool(true);
\\ fn_bool(false);
\\ fn_bool(@ptrToInt(&fn_int) != 0);
\\ fn_int(@intCast(c_int, @ptrToInt(&fn_int)));
\\ fn_ptr(@intToPtr(?*c_void, 42));
\\}
);
// cases.add("empty array with initializer",
// "int a[4] = {};"
// ,