public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Add negation operator overload support
@ 2022-06-08 11:51 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-06-08 11:51 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:04a49acfa3caa7a85a1a9edd24d69da0ad575ad5

commit 04a49acfa3caa7a85a1a9edd24d69da0ad575ad5
Author: Philip Herron <philip.herron@embecosm.com>
Date:   Mon Nov 15 18:13:32 2021 +0000

    Add negation operator overload support
    
    Unary operator expressions can be treated as simply having a nullptr
    rvalue. This patch updates the shared operator overloading code to allow
    for a nullptr rhs to canonicalize the code path for all operator overloads.
    
    Fixes #249

Diff:
---
 gcc/rust/backend/rust-compile-expr.cc              | 31 +++++++++++++++++--
 gcc/rust/backend/rust-compile-expr.h               | 10 +-----
 gcc/rust/typecheck/rust-hir-type-check-expr.h      | 26 +++++++++++++---
 gcc/rust/util/rust-hir-map.h                       | 34 ++++++++++++++------
 .../rust/execute/torture/operator_overload_4.rs    | 36 ++++++++++++++++++++++
 .../rust/execute/torture/operator_overload_5.rs    | 36 ++++++++++++++++++++++
 6 files changed, 147 insertions(+), 26 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 8902574baec..594cfffb498 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -92,6 +92,31 @@ CompileExpr::visit (HIR::CompoundAssignmentExpr &expr)
   ctx->add_statement (assignment);
 }
 
+void
+CompileExpr::visit (HIR::NegationExpr &expr)
+{
+  auto op = expr.get_expr_type ();
+  auto negated_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx);
+  auto location = expr.get_locus ();
+
+  // this might be an operator overload situation lets check
+  TyTy::FnType *fntype;
+  bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
+    expr.get_mappings ().get_hirid (), &fntype);
+  if (is_op_overload)
+    {
+      auto lang_item_type
+	= Analysis::RustLangItem::NegationOperatorToLangItem (op);
+      translated
+	= resolve_operator_overload (lang_item_type, expr, negated_expr,
+				     nullptr, expr.get_expr ().get (), nullptr);
+      return;
+    }
+
+  translated
+    = ctx->get_backend ()->negation_expression (op, negated_expr, location);
+}
+
 Bexpression *
 CompileExpr::compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn,
 					TyTy::BaseType *receiver,
@@ -311,7 +336,8 @@ CompileExpr::resolve_operator_overload (
 	= static_cast<const TyTy::DynamicObjectType *> (receiver->get_root ());
 
       std::vector<HIR::Expr *> arguments;
-      arguments.push_back (rhs_expr);
+      if (rhs_expr != nullptr) // can be null for negation_expr (unary ones)
+	arguments.push_back (rhs_expr);
 
       return compile_dyn_dispatch_call (dyn, receiver, fntype, lhs, arguments,
 					expr.get_locus ());
@@ -356,7 +382,8 @@ CompileExpr::resolve_operator_overload (
 
   std::vector<Bexpression *> args;
   args.push_back (self); // adjusted self
-  args.push_back (rhs);
+  if (rhs != nullptr)	 // can be null for negation_expr (unary ones)
+    args.push_back (rhs);
 
   auto fncontext = ctx->peek_fn ();
   return ctx->get_backend ()->call_expression (fncontext.fndecl, fn_expr, args,
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 7238d45a270..b4079f7e4ac 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -474,15 +474,7 @@ public:
       = ctx->get_backend ()->lazy_boolean_expression (op, lhs, rhs, location);
   }
 
-  void visit (HIR::NegationExpr &expr) override
-  {
-    auto op = expr.get_expr_type ();
-    auto negated_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx);
-    auto location = expr.get_locus ();
-
-    translated
-      = ctx->get_backend ()->negation_expression (op, negated_expr, location);
-  }
+  void visit (HIR::NegationExpr &expr) override;
 
   void visit (HIR::TypeCastExpr &expr) override
   {
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 37cd6b303dd..642bde241d8 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -792,6 +792,15 @@ public:
     auto negated_expr_ty
       = TypeCheckExpr::Resolve (expr.get_expr ().get (), false);
 
+    // check for operator overload
+    auto lang_item_type = Analysis::RustLangItem::NegationOperatorToLangItem (
+      expr.get_expr_type ());
+    bool operator_overloaded
+      = resolve_operator_overload (lang_item_type, expr, negated_expr_ty,
+				   nullptr);
+    if (operator_overloaded)
+      return;
+
     // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators
     switch (expr.get_expr_type ())
       {
@@ -1380,11 +1389,18 @@ protected:
 	  }
       }
 
-    // type check the arguments
+    // type check the arguments if required
     TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup);
-    rust_assert (type->num_params () == 2);
-    auto fnparam = type->param_at (1);
-    fnparam.second->unify (rhs); // typecheck the rhs
+    if (rhs == nullptr)
+      {
+	rust_assert (type->num_params () == 1);
+      }
+    else
+      {
+	rust_assert (type->num_params () == 2);
+	auto fnparam = type->param_at (1);
+	fnparam.second->unify (rhs); // typecheck the rhs
+      }
 
     // get the return type
     TyTy::BaseType *function_ret_tyty = fn->get_return_type ()->clone ();
@@ -1481,7 +1497,7 @@ private:
   Location root_array_expr_locus;
 
   bool inside_loop;
-};
+}; // namespace Resolver
 
 } // namespace Resolver
 } // namespace Rust
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index bcbd582b34b..4f8c3899a33 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -43,6 +43,7 @@ public:
     REMAINDER,
 
     NEGATION,
+    NOT,
 
     ADD_ASSIGN,
     SUB_ASSIGN,
@@ -79,6 +80,10 @@ public:
       {
 	return ItemType::NEGATION;
       }
+    else if (item.compare ("not") == 0)
+      {
+	return ItemType::NOT;
+      }
     else if (item.compare ("add_assign") == 0)
       {
 	return ItemType::ADD_ASSIGN;
@@ -119,6 +124,8 @@ public:
 	return "rem";
       case NEGATION:
 	return "neg";
+      case NOT:
+	return "not";
       case ADD_ASSIGN:
 	return "add_assign";
       case SUB_ASSIGN:
@@ -151,11 +158,7 @@ public:
       case ArithmeticOrLogicalOperator::MODULUS:
 	return ItemType::REMAINDER;
 
-      case ArithmeticOrLogicalOperator::BITWISE_AND:
-      case ArithmeticOrLogicalOperator::BITWISE_OR:
-      case ArithmeticOrLogicalOperator::BITWISE_XOR:
-      case ArithmeticOrLogicalOperator::LEFT_SHIFT:
-      case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
+      default:
 	return ItemType::UNKNOWN;
       }
     return ItemType::UNKNOWN;
@@ -177,11 +180,22 @@ public:
       case ArithmeticOrLogicalOperator::MODULUS:
 	return ItemType::REM_ASSIGN;
 
-      case ArithmeticOrLogicalOperator::BITWISE_AND:
-      case ArithmeticOrLogicalOperator::BITWISE_OR:
-      case ArithmeticOrLogicalOperator::BITWISE_XOR:
-      case ArithmeticOrLogicalOperator::LEFT_SHIFT:
-      case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
+      default:
+	return ItemType::UNKNOWN;
+      }
+    return ItemType::UNKNOWN;
+  }
+
+  static ItemType NegationOperatorToLangItem (NegationOperator op)
+  {
+    switch (op)
+      {
+      case NegationOperator::NEGATE:
+	return ItemType::NEGATION;
+      case NegationOperator::NOT:
+	return ItemType::NOT;
+
+      default:
 	return ItemType::UNKNOWN;
       }
     return ItemType::UNKNOWN;
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_4.rs b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs
new file mode 100644
index 00000000000..eca19de309a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs
@@ -0,0 +1,36 @@
+/* { dg-output "neg\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "neg"]
+pub trait Neg {
+    type Output;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    fn neg(self) -> Self::Output;
+    // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+    // { dg-warning "unused name .Neg::neg." "" { target *-*-* } .-2 }
+}
+
+impl Neg for i32 {
+    type Output = i32;
+
+    fn neg(self) -> i32 {
+        unsafe {
+            let a = "neg\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+        -self
+    }
+}
+
+fn main() -> i32 {
+    let a: i32 = 1;
+    let _b = -a;
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_5.rs b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs
new file mode 100644
index 00000000000..ffdc8c23280
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs
@@ -0,0 +1,36 @@
+/* { dg-output "not\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "not"]
+pub trait Not {
+    type Output;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+    fn not(self) -> Self::Output;
+    // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+    // { dg-warning "unused name .Not::not." "" { target *-*-* } .-2 }
+}
+
+impl Not for i32 {
+    type Output = i32;
+
+    fn not(self) -> i32 {
+        unsafe {
+            let a = "not\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+        !self
+    }
+}
+
+fn main() -> i32 {
+    let a: i32 = 1;
+    let _b = !a;
+
+    0
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-08 11:51 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-08 11:51 [gcc/devel/rust/master] Add negation operator overload support Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).