diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-01-19 17:02:45 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-01-20 10:03:50 +0000 |
commit | 85d8754632d597fe3d94404406082bcbb2f5ff94 (patch) | |
tree | a118c7d4e6c294fb2b775da8fb75efad6227b0f0 /gcc | |
parent | 6e09093f1f759a78387d214b6d0fe8ba17b752b6 (diff) | |
download | gcc-85d8754632d597fe3d94404406082bcbb2f5ff94.zip gcc-85d8754632d597fe3d94404406082bcbb2f5ff94.tar.gz gcc-85d8754632d597fe3d94404406082bcbb2f5ff94.tar.bz2 |
Implement NegationExpression
This is an example of a unary expression in gimple. The rules for enforcing
the types are observed in the type resolver here too.
Unary negate cannot be applied to bools but only integers and floats.
Unary not cannot be applied to floating points but can be applied to
integers and bools.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 19 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-expr.h | 28 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.h | 5 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 39 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/unary_operators.rs | 6 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/fail_compilation/unary_negation.rs | 8 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/fail_compilation/unary_not.rs | 8 |
7 files changed, 113 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index ff02d6b..da3c9cd 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -378,6 +378,25 @@ public: expr.get_locus ()); } + void visit (HIR::NegationExpr &expr) + { + Operator op (OPERATOR_INVALID); + switch (expr.get_negation_type ()) + { + case HIR::NegationExpr::NegationType::NEGATE: + op = OPERATOR_MINUS; + break; + + case HIR::NegationExpr::NegationType::NOT: + op = OPERATOR_NOT; + break; + } + + Bexpression *negated_expr = CompileExpr::Compile (expr.get_expr (), ctx); + translated = ctx->get_backend ()->unary_expression (op, negated_expr, + expr.get_locus ()); + } + void visit (HIR::IfExpr &expr) { auto stmt = CompileConditionalBlocks::compile (&expr, ctx); diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 6f872ab..a924ef2 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -504,6 +504,34 @@ public: expr.get_locus ()); } + void visit (AST::NegationExpr &expr) + { + std::vector<HIR::Attribute> outer_attribs; + + HIR::NegationExpr::NegationType type; + switch (expr.get_negation_type ()) + { + case AST::NegationExpr::NegationType::NEGATE: + type = HIR::NegationExpr::NegationType::NEGATE; + break; + case AST::NegationExpr::NegationType::NOT: + type = HIR::NegationExpr::NegationType::NOT; + break; + } + + HIR::Expr *negated_value + = ASTLoweringExpr::translate (expr.get_negated_expr ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + translated + = new HIR::NegationExpr (mapping, + std::unique_ptr<HIR::Expr> (negated_value), type, + std::move (outer_attribs), expr.get_locus ()); + } + void visit (AST::StructExprStructFields &struct_expr) { std::vector<HIR::Attribute> inner_attribs; diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 181124a..03b3496 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -128,6 +128,11 @@ public: ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ()); } + void visit (AST::NegationExpr &expr) + { + ResolveExpr::go (expr.get_negated_expr ().get (), expr.get_node_id ()); + } + void visit (AST::IfExpr &expr) { ResolveExpr::go (expr.get_condition_expr ().get (), expr.get_node_id ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 419b911..02830cd 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -456,6 +456,45 @@ public: infered = lhs->combine (rhs); } + void visit (HIR::NegationExpr &expr) + { + auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ()); + + // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators + switch (expr.get_negation_type ()) + { + case HIR::NegationExpr::NegationType::NEGATE: { + bool valid + = (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::FLOAT); + if (!valid) + { + rust_error_at (expr.get_locus (), "cannot apply unary - to %s", + negated_expr_ty->as_string ().c_str ()); + return; + } + } + break; + + case HIR::NegationExpr::NegationType::NOT: { + bool valid + = (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT); + if (!valid) + { + rust_error_at (expr.get_locus (), "cannot apply unary ! to %s", + negated_expr_ty->as_string ().c_str ()); + return; + } + } + break; + } + + infered = negated_expr_ty; + } + void visit (HIR::IfExpr &expr) { TypeCheckExpr::Resolve (expr.get_if_condition ()); diff --git a/gcc/testsuite/rust.test/compilable/unary_operators.rs b/gcc/testsuite/rust.test/compilable/unary_operators.rs new file mode 100644 index 0000000..1ed9666 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/unary_operators.rs @@ -0,0 +1,6 @@ +fn main() { + let a: i32 = -1; + let b: i32 = 3 - -1; + let c: bool = !false; + let d: i32 = !3; +} diff --git a/gcc/testsuite/rust.test/fail_compilation/unary_negation.rs b/gcc/testsuite/rust.test/fail_compilation/unary_negation.rs new file mode 100644 index 0000000..476b908 --- /dev/null +++ b/gcc/testsuite/rust.test/fail_compilation/unary_negation.rs @@ -0,0 +1,8 @@ +fn main() { + let a: i32 = -1; + let b: i32 = 3 - -1; + let c: bool = !false; + let d: i32 = !3; + + let e: f32 = -true; +} diff --git a/gcc/testsuite/rust.test/fail_compilation/unary_not.rs b/gcc/testsuite/rust.test/fail_compilation/unary_not.rs new file mode 100644 index 0000000..f358f0e --- /dev/null +++ b/gcc/testsuite/rust.test/fail_compilation/unary_not.rs @@ -0,0 +1,8 @@ +fn main() { + let a: i32 = -1; + let b: i32 = 3 - -1; + let c: bool = !false; + let d: i32 = !3; + + let e: f32 = !5f32; +} |