Skip to content

Commit fc809a9

Browse files
committed
Add negation operator overload support
unary rhs nullptr refactor Fixes #249
1 parent 1fbf519 commit fc809a9

File tree

6 files changed

+147
-26
lines changed

6 files changed

+147
-26
lines changed

gcc/rust/backend/rust-compile-expr.cc

+29-2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,31 @@ CompileExpr::visit (HIR::CompoundAssignmentExpr &expr)
9292
ctx->add_statement (assignment);
9393
}
9494

95+
void
96+
CompileExpr::visit (HIR::NegationExpr &expr)
97+
{
98+
auto op = expr.get_expr_type ();
99+
auto negated_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx);
100+
auto location = expr.get_locus ();
101+
102+
// this might be an operator overload situation lets check
103+
TyTy::FnType *fntype;
104+
bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
105+
expr.get_mappings ().get_hirid (), &fntype);
106+
if (is_op_overload)
107+
{
108+
auto lang_item_type
109+
= Analysis::RustLangItem::NegationOperatorToLangItem (op);
110+
translated
111+
= resolve_operator_overload (lang_item_type, expr, negated_expr,
112+
nullptr, expr.get_expr ().get (), nullptr);
113+
return;
114+
}
115+
116+
translated
117+
= ctx->get_backend ()->negation_expression (op, negated_expr, location);
118+
}
119+
95120
Bexpression *
96121
CompileExpr::compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn,
97122
TyTy::BaseType *receiver,
@@ -311,7 +336,8 @@ CompileExpr::resolve_operator_overload (
311336
= static_cast<const TyTy::DynamicObjectType *> (receiver->get_root ());
312337

313338
std::vector<HIR::Expr *> arguments;
314-
arguments.push_back (rhs_expr);
339+
if (rhs_expr != nullptr) // can be null for negation_expr (unary ones)
340+
arguments.push_back (rhs_expr);
315341

316342
return compile_dyn_dispatch_call (dyn, receiver, fntype, lhs, arguments,
317343
expr.get_locus ());
@@ -356,7 +382,8 @@ CompileExpr::resolve_operator_overload (
356382

357383
std::vector<Bexpression *> args;
358384
args.push_back (self); // adjusted self
359-
args.push_back (rhs);
385+
if (rhs != nullptr) // can be null for negation_expr (unary ones)
386+
args.push_back (rhs);
360387

361388
auto fncontext = ctx->peek_fn ();
362389
return ctx->get_backend ()->call_expression (fncontext.fndecl, fn_expr, args,

gcc/rust/backend/rust-compile-expr.h

+1-9
Original file line numberDiff line numberDiff line change
@@ -474,15 +474,7 @@ class CompileExpr : public HIRCompileBase
474474
= ctx->get_backend ()->lazy_boolean_expression (op, lhs, rhs, location);
475475
}
476476

477-
void visit (HIR::NegationExpr &expr) override
478-
{
479-
auto op = expr.get_expr_type ();
480-
auto negated_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx);
481-
auto location = expr.get_locus ();
482-
483-
translated
484-
= ctx->get_backend ()->negation_expression (op, negated_expr, location);
485-
}
477+
void visit (HIR::NegationExpr &expr) override;
486478

487479
void visit (HIR::TypeCastExpr &expr) override
488480
{

gcc/rust/typecheck/rust-hir-type-check-expr.h

+21-5
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,15 @@ class TypeCheckExpr : public TypeCheckBase
792792
auto negated_expr_ty
793793
= TypeCheckExpr::Resolve (expr.get_expr ().get (), false);
794794

795+
// check for operator overload
796+
auto lang_item_type = Analysis::RustLangItem::NegationOperatorToLangItem (
797+
expr.get_expr_type ());
798+
bool operator_overloaded
799+
= resolve_operator_overload (lang_item_type, expr, negated_expr_ty,
800+
nullptr);
801+
if (operator_overloaded)
802+
return;
803+
795804
// https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators
796805
switch (expr.get_expr_type ())
797806
{
@@ -1380,11 +1389,18 @@ class TypeCheckExpr : public TypeCheckBase
13801389
}
13811390
}
13821391

1383-
// type check the arguments
1392+
// type check the arguments if required
13841393
TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup);
1385-
rust_assert (type->num_params () == 2);
1386-
auto fnparam = type->param_at (1);
1387-
fnparam.second->unify (rhs); // typecheck the rhs
1394+
if (rhs == nullptr)
1395+
{
1396+
rust_assert (type->num_params () == 1);
1397+
}
1398+
else
1399+
{
1400+
rust_assert (type->num_params () == 2);
1401+
auto fnparam = type->param_at (1);
1402+
fnparam.second->unify (rhs); // typecheck the rhs
1403+
}
13881404

13891405
// get the return type
13901406
TyTy::BaseType *function_ret_tyty = fn->get_return_type ()->clone ();
@@ -1481,7 +1497,7 @@ class TypeCheckExpr : public TypeCheckBase
14811497
Location root_array_expr_locus;
14821498

14831499
bool inside_loop;
1484-
};
1500+
}; // namespace Resolver
14851501

14861502
} // namespace Resolver
14871503
} // namespace Rust

gcc/rust/util/rust-hir-map.h

+24-10
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class RustLangItem
4343
REMAINDER,
4444

4545
NEGATION,
46+
NOT,
4647

4748
ADD_ASSIGN,
4849
SUB_ASSIGN,
@@ -79,6 +80,10 @@ class RustLangItem
7980
{
8081
return ItemType::NEGATION;
8182
}
83+
else if (item.compare ("not") == 0)
84+
{
85+
return ItemType::NOT;
86+
}
8287
else if (item.compare ("add_assign") == 0)
8388
{
8489
return ItemType::ADD_ASSIGN;
@@ -119,6 +124,8 @@ class RustLangItem
119124
return "rem";
120125
case NEGATION:
121126
return "neg";
127+
case NOT:
128+
return "not";
122129
case ADD_ASSIGN:
123130
return "add_assign";
124131
case SUB_ASSIGN:
@@ -151,11 +158,7 @@ class RustLangItem
151158
case ArithmeticOrLogicalOperator::MODULUS:
152159
return ItemType::REMAINDER;
153160

154-
case ArithmeticOrLogicalOperator::BITWISE_AND:
155-
case ArithmeticOrLogicalOperator::BITWISE_OR:
156-
case ArithmeticOrLogicalOperator::BITWISE_XOR:
157-
case ArithmeticOrLogicalOperator::LEFT_SHIFT:
158-
case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
161+
default:
159162
return ItemType::UNKNOWN;
160163
}
161164
return ItemType::UNKNOWN;
@@ -177,11 +180,22 @@ class RustLangItem
177180
case ArithmeticOrLogicalOperator::MODULUS:
178181
return ItemType::REM_ASSIGN;
179182

180-
case ArithmeticOrLogicalOperator::BITWISE_AND:
181-
case ArithmeticOrLogicalOperator::BITWISE_OR:
182-
case ArithmeticOrLogicalOperator::BITWISE_XOR:
183-
case ArithmeticOrLogicalOperator::LEFT_SHIFT:
184-
case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
183+
default:
184+
return ItemType::UNKNOWN;
185+
}
186+
return ItemType::UNKNOWN;
187+
}
188+
189+
static ItemType NegationOperatorToLangItem (NegationOperator op)
190+
{
191+
switch (op)
192+
{
193+
case NegationOperator::NEGATE:
194+
return ItemType::NEGATION;
195+
case NegationOperator::NOT:
196+
return ItemType::NOT;
197+
198+
default:
185199
return ItemType::UNKNOWN;
186200
}
187201
return ItemType::UNKNOWN;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* { dg-output "neg\n" } */
2+
extern "C" {
3+
fn printf(s: *const i8, ...);
4+
}
5+
6+
#[lang = "neg"]
7+
pub trait Neg {
8+
type Output;
9+
// { dg-warning "unused name" "" { target *-*-* } .-1 }
10+
11+
fn neg(self) -> Self::Output;
12+
// { dg-warning "unused name .self." "" { target *-*-* } .-1 }
13+
// { dg-warning "unused name .Neg::neg." "" { target *-*-* } .-2 }
14+
}
15+
16+
impl Neg for i32 {
17+
type Output = i32;
18+
19+
fn neg(self) -> i32 {
20+
unsafe {
21+
let a = "neg\n\0";
22+
let b = a as *const str;
23+
let c = b as *const i8;
24+
25+
printf(c);
26+
}
27+
-self
28+
}
29+
}
30+
31+
fn main() -> i32 {
32+
let a: i32 = 1;
33+
let _b = -a;
34+
35+
0
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* { dg-output "not\n" } */
2+
extern "C" {
3+
fn printf(s: *const i8, ...);
4+
}
5+
6+
#[lang = "not"]
7+
pub trait Not {
8+
type Output;
9+
// { dg-warning "unused name" "" { target *-*-* } .-1 }
10+
11+
fn not(self) -> Self::Output;
12+
// { dg-warning "unused name .self." "" { target *-*-* } .-1 }
13+
// { dg-warning "unused name .Not::not." "" { target *-*-* } .-2 }
14+
}
15+
16+
impl Not for i32 {
17+
type Output = i32;
18+
19+
fn not(self) -> i32 {
20+
unsafe {
21+
let a = "not\n\0";
22+
let b = a as *const str;
23+
let c = b as *const i8;
24+
25+
printf(c);
26+
}
27+
!self
28+
}
29+
}
30+
31+
fn main() -> i32 {
32+
let a: i32 = 1;
33+
let _b = !a;
34+
35+
0
36+
}

0 commit comments

Comments
 (0)