aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile-expr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/backend/rust-compile-expr.cc')
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc207
1 files changed, 207 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 5e43f5a..9b04bbf 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 {
@@ -886,5 +888,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