diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-04-24 14:43:46 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-04-24 14:43:46 -0400 |
| commit | ad994c96423dd1fcf81d3069aa2d39e345a0aeba (patch) | |
| tree | e1a4514018fdd60fd496291a4382e9d2e6a2c8b7 /src | |
| parent | 7bafe2e490576f8b6f401ed4e9cedfa9fb395127 (diff) | |
| parent | 70c2e86da36abdd56fd61b77682643129fcf6371 (diff) | |
| download | zig-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.cpp | 2 | ||||
| -rw-r--r-- | src/ir.cpp | 6 | ||||
| -rw-r--r-- | src/translate_c.cpp | 157 |
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; |
