aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-04-24 14:43:46 -0400
committerGitHub <noreply@github.com>2019-04-24 14:43:46 -0400
commitad994c96423dd1fcf81d3069aa2d39e345a0aeba (patch)
treee1a4514018fdd60fd496291a4382e9d2e6a2c8b7 /src
parent7bafe2e490576f8b6f401ed4e9cedfa9fb395127 (diff)
parent70c2e86da36abdd56fd61b77682643129fcf6371 (diff)
downloadzig-ad994c96423dd1fcf81d3069aa2d39e345a0aeba.tar.gz
zig-ad994c96423dd1fcf81d3069aa2d39e345a0aeba.zip
Merge pull request #2296 from LemonBoy/translate-c-stuff
Handle implicit casts in translate-c
Diffstat (limited to 'src')
-rw-r--r--src/ast_render.cpp2
-rw-r--r--src/ir.cpp6
-rw-r--r--src/translate_c.cpp157
3 files changed, 146 insertions, 19 deletions
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index 16f2aafa78..f66a47600e 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -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;
}
diff --git a/src/ir.cpp b/src/ir.cpp
index e5192cf347..f3435ccb17 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -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;
diff --git a/src/translate_c.cpp b/src/translate_c.cpp
index 43783cf1c0..f4f1055ed9 100644
--- a/src/translate_c.cpp
+++ b/src/translate_c.cpp
@@ -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;