Merge pull request #2296 from LemonBoy/translate-c-stuff
Handle implicit casts in translate-c
This commit is contained in:
commit
ad994c9642
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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] = {};"
|
||||
// ,
|
||||
|
Loading…
x
Reference in New Issue
Block a user