aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc207
-rw-r--r--gcc/rust/backend/rust-compile-expr.h166
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-const-fold.h6
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h10
-rw-r--r--gcc/rust/typecheck/rust-tycheck-dump.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty-cast.h2
-rw-r--r--gcc/testsuite/rust/compile/issue-635-1.rs5
-rw-r--r--gcc/testsuite/rust/compile/issue-635-2.rs5
9 files changed, 278 insertions, 128 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index b77a4d5..0307b21 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -27,6 +27,8 @@
#include "rust-compile-pattern.h"
#include "fold-const.h"
+#include "realmpfr.h"
+#include "convert.h"
namespace Rust {
namespace Compile {
@@ -893,5 +895,210 @@ CompileExpr::resolve_operator_overload (
nullptr, expr.get_locus ());
}
+tree
+CompileExpr::compile_bool_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty)
+{
+ rust_assert (expr.get_lit_type () == HIR::Literal::BOOL);
+
+ const auto literal_value = expr.get_literal ();
+ bool bval = literal_value.as_string ().compare ("true") == 0;
+ return ctx->get_backend ()->boolean_constant_expression (bval);
+}
+
+tree
+CompileExpr::compile_integer_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty)
+{
+ rust_assert (expr.get_lit_type () == HIR::Literal::INT);
+ const auto literal_value = expr.get_literal ();
+
+ tree type = TyTyResolveCompile::compile (ctx, tyty);
+ rust_assert (TREE_CODE (type) == INTEGER_TYPE);
+
+ mpz_t ival;
+ if (mpz_init_set_str (ival, literal_value.as_string ().c_str (), 10) != 0)
+ {
+ rust_error_at (expr.get_locus (), "bad number in literal");
+ return error_mark_node;
+ }
+
+ mpz_t type_min;
+ mpz_t type_max;
+ mpz_init (type_min);
+ mpz_init (type_max);
+ get_type_static_bounds (type, type_min, type_max);
+
+ if (mpz_cmp (ival, type_min) < 0 || mpz_cmp (ival, type_max) > 0)
+ {
+ rust_error_at (expr.get_locus (),
+ "integer overflows the respective type %<%s%>",
+ tyty->get_name ().c_str ());
+ return error_mark_node;
+ }
+ return double_int_to_tree (type, mpz_get_double_int (type, ival, true));
+}
+
+tree
+CompileExpr::compile_float_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty)
+{
+ rust_assert (expr.get_lit_type () == HIR::Literal::FLOAT);
+ const auto literal_value = expr.get_literal ();
+
+ mpfr_t fval;
+ if (mpfr_init_set_str (fval, literal_value.as_string ().c_str (), 10,
+ MPFR_RNDN)
+ != 0)
+ {
+ rust_error_at (expr.get_locus (), "bad number in literal");
+ return error_mark_node;
+ }
+
+ tree type = TyTyResolveCompile::compile (ctx, tyty);
+
+ // taken from:
+ // see go/gofrontend/expressions.cc:check_float_type
+ mpfr_exp_t exp = mpfr_get_exp (fval);
+ bool real_value_overflow = exp > TYPE_PRECISION (type);
+
+ REAL_VALUE_TYPE r1;
+ real_from_mpfr (&r1, fval, type, GMP_RNDN);
+ REAL_VALUE_TYPE r2;
+ real_convert (&r2, TYPE_MODE (type), &r1);
+
+ tree real_value = build_real (type, r2);
+ if (TREE_OVERFLOW (real_value) || real_value_overflow)
+ {
+ rust_error_at (expr.get_locus (),
+ "decimal overflows the respective type %<%s%>",
+ tyty->get_name ().c_str ());
+ return error_mark_node;
+ }
+
+ return real_value;
+}
+
+tree
+CompileExpr::compile_char_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty)
+{
+ rust_assert (expr.get_lit_type () == HIR::Literal::CHAR);
+ const auto literal_value = expr.get_literal ();
+
+ // FIXME needs wchar_t
+ char c = literal_value.as_string ().c_str ()[0];
+ return ctx->get_backend ()->wchar_constant_expression (c);
+}
+
+tree
+CompileExpr::compile_byte_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty)
+{
+ rust_assert (expr.get_lit_type () == HIR::Literal::BYTE);
+ const auto literal_value = expr.get_literal ();
+
+ tree type = TyTyResolveCompile::compile (ctx, tyty);
+ char c = literal_value.as_string ().c_str ()[0];
+ return build_int_cst (type, c);
+}
+
+tree
+CompileExpr::compile_string_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty)
+{
+ rust_assert (expr.get_lit_type () == HIR::Literal::STRING);
+ const auto literal_value = expr.get_literal ();
+
+ auto base = ctx->get_backend ()->string_constant_expression (
+ literal_value.as_string ());
+ return ctx->get_backend ()->address_expression (base, expr.get_locus ());
+}
+
+tree
+CompileExpr::compile_byte_string_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty)
+{
+ rust_assert (expr.get_lit_type () == HIR::Literal::BYTE_STRING);
+
+ // the type here is &[ty; capacity]
+ rust_assert (tyty->get_kind () == TyTy::TypeKind::REF);
+ const auto ref_tyty = static_cast<const TyTy::ReferenceType *> (tyty);
+ auto base_tyty = ref_tyty->get_base ();
+ rust_assert (base_tyty->get_kind () == TyTy::TypeKind::ARRAY);
+ auto array_tyty = static_cast<TyTy::ArrayType *> (base_tyty);
+
+ std::string value_str = expr.get_literal ().as_string ();
+ std::vector<tree> vals;
+ std::vector<unsigned long> indexes;
+ for (size_t i = 0; i < value_str.size (); i++)
+ {
+ char b = value_str.at (i);
+ tree bb = ctx->get_backend ()->char_constant_expression (b);
+ vals.push_back (bb);
+ indexes.push_back (i);
+ }
+
+ tree array_type = TyTyResolveCompile::compile (ctx, array_tyty);
+ tree constructed
+ = ctx->get_backend ()->array_constructor_expression (array_type, indexes,
+ vals,
+ expr.get_locus ());
+
+ return ctx->get_backend ()->address_expression (constructed,
+ expr.get_locus ());
+}
+
+tree
+CompileExpr::type_cast_expression (tree type_to_cast_to, tree expr_tree,
+ Location location)
+{
+ if (type_to_cast_to == error_mark_node || expr_tree == error_mark_node
+ || TREE_TYPE (expr_tree) == error_mark_node)
+ return error_mark_node;
+
+ if (ctx->get_backend ()->type_size (type_to_cast_to) == 0
+ || TREE_TYPE (expr_tree) == void_type_node)
+ {
+ // Do not convert zero-sized types.
+ return expr_tree;
+ }
+ else if (TREE_CODE (type_to_cast_to) == INTEGER_TYPE)
+ {
+ tree cast = fold (convert_to_integer (type_to_cast_to, expr_tree));
+ // FIXME check for TREE_OVERFLOW?
+ return cast;
+ }
+ else if (TREE_CODE (type_to_cast_to) == REAL_TYPE)
+ {
+ tree cast = fold (convert_to_real (type_to_cast_to, expr_tree));
+ // FIXME
+ // We might need to check that the tree is MAX val and thusly saturate it
+ // to inf. we can get the bounds and check the value if its >= or <= to
+ // the min and max bounds
+ //
+ // https://github.com/Rust-GCC/gccrs/issues/635
+ return cast;
+ }
+ else if (TREE_CODE (type_to_cast_to) == COMPLEX_TYPE)
+ {
+ return fold (convert_to_complex (type_to_cast_to, expr_tree));
+ }
+ else if (TREE_CODE (type_to_cast_to) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (expr_tree)) == INTEGER_TYPE)
+ {
+ return fold (convert_to_pointer (type_to_cast_to, expr_tree));
+ }
+ else if (TREE_CODE (type_to_cast_to) == RECORD_TYPE
+ || TREE_CODE (type_to_cast_to) == ARRAY_TYPE)
+ {
+ return fold_build1_loc (location.gcc_location (), VIEW_CONVERT_EXPR,
+ type_to_cast_to, expr_tree);
+ }
+
+ return fold_convert_loc (location.gcc_location (), type_to_cast_to,
+ expr_tree);
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index dc4f909..2f44621 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -234,132 +234,41 @@ public:
void visit (HIR::LiteralExpr &expr) override
{
- auto literal_value = expr.get_literal ();
+ TyTy::BaseType *tyty = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &tyty))
+ return;
+
switch (expr.get_lit_type ())
{
- case HIR::Literal::BOOL: {
- bool bval = literal_value->as_string ().compare ("true") == 0;
- translated = ctx->get_backend ()->boolean_constant_expression (bval);
- }
+ case HIR::Literal::BOOL:
+ translated = compile_bool_literal (expr, tyty);
return;
- case HIR::Literal::INT: {
- mpz_t ival;
- if (mpz_init_set_str (ival, literal_value->as_string ().c_str (), 10)
- != 0)
- {
- rust_fatal_error (expr.get_locus (), "bad number in literal");
- return;
- }
-
- TyTy::BaseType *tyty = nullptr;
- if (!ctx->get_tyctx ()->lookup_type (
- expr.get_mappings ().get_hirid (), &tyty))
- {
- rust_fatal_error (
- expr.get_locus (),
- "did not resolve type for this literal expr (HirId %d)",
- expr.get_mappings ().get_hirid ());
- return;
- }
-
- tree type = TyTyResolveCompile::compile (ctx, tyty);
- translated
- = ctx->get_backend ()->integer_constant_expression (type, ival);
- }
+ case HIR::Literal::INT:
+ translated = compile_integer_literal (expr, tyty);
return;
- case HIR::Literal::FLOAT: {
- mpfr_t fval;
- if (mpfr_init_set_str (fval, literal_value->as_string ().c_str (), 10,
- MPFR_RNDN)
- != 0)
- {
- rust_fatal_error (expr.get_locus (),
- "bad floating-point number in literal");
- return;
- }
-
- TyTy::BaseType *tyty = nullptr;
- if (!ctx->get_tyctx ()->lookup_type (
- expr.get_mappings ().get_hirid (), &tyty))
- {
- rust_fatal_error (expr.get_locus (),
- "did not resolve type for this literal expr");
- return;
- }
-
- tree type = TyTyResolveCompile::compile (ctx, tyty);
- translated
- = ctx->get_backend ()->float_constant_expression (type, fval);
- }
+ case HIR::Literal::FLOAT:
+ translated = compile_float_literal (expr, tyty);
return;
- case HIR::Literal::CHAR: {
- // FIXME needs wchar_t
- char c = literal_value->as_string ().c_str ()[0];
- translated = ctx->get_backend ()->wchar_constant_expression (c);
- }
+ case HIR::Literal::CHAR:
+ translated = compile_char_literal (expr, tyty);
return;
- case HIR::Literal::BYTE: {
- char c = literal_value->as_string ().c_str ()[0];
- translated = ctx->get_backend ()->char_constant_expression (c);
- }
+ case HIR::Literal::BYTE:
+ translated = compile_byte_literal (expr, tyty);
return;
- case HIR::Literal::STRING: {
- auto base = ctx->get_backend ()->string_constant_expression (
- literal_value->as_string ());
- translated
- = ctx->get_backend ()->address_expression (base, expr.get_locus ());
- }
+ case HIR::Literal::STRING:
+ translated = compile_string_literal (expr, tyty);
return;
- case HIR::Literal::BYTE_STRING: {
- TyTy::BaseType *tyty = nullptr;
- if (!ctx->get_tyctx ()->lookup_type (
- expr.get_mappings ().get_hirid (), &tyty))
- {
- rust_error_at (expr.get_locus (),
- "did not resolve type for this byte string");
- return;
- }
-
- // the type here is &[ty; capacity]
- rust_assert (tyty->get_kind () == TyTy::TypeKind::REF);
- auto ref_tyty = static_cast<TyTy::ReferenceType *> (tyty);
- auto base_tyty = ref_tyty->get_base ();
- rust_assert (base_tyty->get_kind () == TyTy::TypeKind::ARRAY);
- auto array_tyty = static_cast<TyTy::ArrayType *> (base_tyty);
-
- std::string value_str = expr.get_literal ()->as_string ();
- std::vector<tree> vals;
- std::vector<unsigned long> indexes;
- for (size_t i = 0; i < value_str.size (); i++)
- {
- char b = value_str.at (i);
- tree bb = ctx->get_backend ()->char_constant_expression (b);
- vals.push_back (bb);
- indexes.push_back (i);
- }
-
- tree array_type = TyTyResolveCompile::compile (ctx, array_tyty);
- tree constructed = ctx->get_backend ()->array_constructor_expression (
- array_type, indexes, vals, expr.get_locus ());
-
- translated
- = ctx->get_backend ()->address_expression (constructed,
- expr.get_locus ());
- }
- return;
-
- default:
- rust_fatal_error (expr.get_locus (), "unknown literal");
+ case HIR::Literal::BYTE_STRING:
+ translated = compile_byte_string_literal (expr, tyty);
return;
}
-
- gcc_unreachable ();
}
void visit (HIR::AssignmentExpr &expr) override
@@ -502,20 +411,19 @@ public:
void visit (HIR::TypeCastExpr &expr) override
{
- TyTy::BaseType *tyty_to_cast_to = nullptr;
+ TyTy::BaseType *tyty = nullptr;
if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
- &tyty_to_cast_to))
+ &tyty))
{
- translated = ctx->get_backend ()->error_expression ();
+ translated = error_mark_node;
return;
}
- auto type_to_cast_to = TyTyResolveCompile::compile (ctx, tyty_to_cast_to);
+ auto type_to_cast_to = TyTyResolveCompile::compile (ctx, tyty);
auto casted_expr
= CompileExpr::Compile (expr.get_casted_expr ().get (), ctx);
translated
- = ctx->get_backend ()->convert_expression (type_to_cast_to, casted_expr,
- expr.get_locus ());
+ = type_cast_expression (type_to_cast_to, casted_expr, expr.get_locus ());
}
void visit (HIR::IfExpr &expr) override
@@ -1067,9 +975,33 @@ protected:
HIR::OperatorExpr &expr, tree lhs, tree rhs,
HIR::Expr *lhs_expr, HIR::Expr *rhs_expr);
+ tree compile_bool_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty);
+
+ tree compile_integer_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty);
+
+ tree compile_float_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty);
+
+ tree compile_char_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty);
+
+ tree compile_byte_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty);
+
+ tree compile_string_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty);
+
+ tree compile_byte_string_literal (const HIR::LiteralExpr &expr,
+ const TyTy::BaseType *tyty);
+
+ tree type_cast_expression (tree type_to_cast_to, tree expr, Location locus);
+
private:
CompileExpr (Context *ctx)
- : HIRCompileBase (ctx), translated (nullptr), capacity_expr (nullptr)
+ : HIRCompileBase (ctx), translated (error_mark_node),
+ capacity_expr (nullptr)
{}
tree translated;
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index 6784550..c1495d4 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -95,7 +95,8 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
- Literal *get_literal () { return &literal; }
+ Literal &get_literal () { return literal; }
+ const Literal &get_literal () const { return literal; }
protected:
/* Use covariance to implement clone function as returning this object rather
diff --git a/gcc/rust/typecheck/rust-hir-const-fold.h b/gcc/rust/typecheck/rust-hir-const-fold.h
index d1f7127..1907816 100644
--- a/gcc/rust/typecheck/rust-hir-const-fold.h
+++ b/gcc/rust/typecheck/rust-hir-const-fold.h
@@ -354,7 +354,7 @@ public:
{
case HIR::Literal::INT: {
mpz_t ival;
- if (mpz_init_set_str (ival, literal_value->as_string ().c_str (), 10)
+ if (mpz_init_set_str (ival, literal_value.as_string ().c_str (), 10)
!= 0)
{
rust_fatal_error (expr.get_locus (), "bad number in literal");
@@ -376,14 +376,14 @@ public:
return;
case HIR::Literal::BOOL: {
- bool bval = literal_value->as_string ().compare ("true") == 0;
+ bool bval = literal_value.as_string ().compare ("true") == 0;
folded = ctx->get_backend ()->boolean_constant_expression (bval);
}
return;
case HIR::Literal::FLOAT: {
mpfr_t fval;
- if (mpfr_init_set_str (fval, literal_value->as_string ().c_str (), 10,
+ if (mpfr_init_set_str (fval, literal_value.as_string ().c_str (), 10,
MPFR_RNDN)
!= 0)
{
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 8de736d..cb3aa6a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -604,7 +604,7 @@ public:
case HIR::Literal::LitType::INT: {
bool ok = false;
- switch (expr.get_literal ()->get_type_hint ())
+ switch (expr.get_literal ().get_type_hint ())
{
case CORETYPE_I8:
ok = context->lookup_builtin ("i8", &infered);
@@ -639,11 +639,11 @@ public:
break;
case CORETYPE_F32:
- expr.get_literal ()->set_lit_type (HIR::Literal::LitType::FLOAT);
+ expr.get_literal ().set_lit_type (HIR::Literal::LitType::FLOAT);
ok = context->lookup_builtin ("f32", &infered);
break;
case CORETYPE_F64:
- expr.get_literal ()->set_lit_type (HIR::Literal::LitType::FLOAT);
+ expr.get_literal ().set_lit_type (HIR::Literal::LitType::FLOAT);
ok = context->lookup_builtin ("f64", &infered);
break;
@@ -661,7 +661,7 @@ public:
case HIR::Literal::LitType::FLOAT: {
bool ok = false;
- switch (expr.get_literal ()->get_type_hint ())
+ switch (expr.get_literal ().get_type_hint ())
{
case CORETYPE_F32:
ok = context->lookup_builtin ("f32", &infered);
@@ -727,7 +727,7 @@ public:
/* Capacity is the size of the string (number of chars).
It is a constant, but for fold it to get a tree. */
std::string capacity_str
- = std::to_string (expr.get_literal ()->as_string ().size ());
+ = std::to_string (expr.get_literal ().as_string ().size ());
HIR::LiteralExpr literal_capacity (capacity_mapping, capacity_str,
HIR::Literal::LitType::INT,
PrimitiveCoreType::CORETYPE_USIZE,
diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h
index c7219cd..33a4b11 100644
--- a/gcc/rust/typecheck/rust-tycheck-dump.h
+++ b/gcc/rust/typecheck/rust-tycheck-dump.h
@@ -141,7 +141,7 @@ public:
void visit (HIR::LiteralExpr &expr) override
{
- dump += expr.get_literal ()->as_string () + ":"
+ dump += expr.get_literal ().as_string () + ":"
+ type_string (expr.get_mappings ());
}
diff --git a/gcc/rust/typecheck/rust-tyty-cast.h b/gcc/rust/typecheck/rust-tyty-cast.h
index aaa589b..07fedd0 100644
--- a/gcc/rust/typecheck/rust-tyty-cast.h
+++ b/gcc/rust/typecheck/rust-tyty-cast.h
@@ -444,7 +444,7 @@ public:
void visit (FloatType &type) override
{
bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL)
|| (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT);
if (is_valid)
{
diff --git a/gcc/testsuite/rust/compile/issue-635-1.rs b/gcc/testsuite/rust/compile/issue-635-1.rs
new file mode 100644
index 0000000..dc6a4c2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-635-1.rs
@@ -0,0 +1,5 @@
+// { dg-additional-options "-w" }
+fn test() -> i32 {
+ return 10000000000000000000000000000000000000000000;
+ // { dg-error "integer overflows the respective type .i32." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-635-2.rs b/gcc/testsuite/rust/compile/issue-635-2.rs
new file mode 100644
index 0000000..335218a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-635-2.rs
@@ -0,0 +1,5 @@
+// { dg-additional-options "-w" }
+fn test() -> f32 {
+ return 10000000000000000000000000000000000000000000.0f32;
+ // { dg-error "decimal overflows the respective type .f32." "" { target *-*-* } .-1 }
+}