Skip to content

Commit fae24e5

Browse files
committed
Unbox variables used in ternary operators
1 parent 51dc57c commit fae24e5

12 files changed

Lines changed: 336 additions & 61 deletions

‎cpp2rust/converter/models/boxed_vars.cpp‎

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ bool IsFlatVec(clang::QualType type) {
3232
}
3333

3434
// Whether decl may be stored without a Value, if its address is not taken:
35-
// scalars, arrays of non-arrays, user-defined structs, unique_ptrs and
36-
// vectors, unless they have a destructor, which is called with a pointer to
37-
// them.
38-
bool CanUnbox(const clang::VarDecl *decl) {
35+
// scalars, arrays of non-arrays, user-defined structs, unique_ptrs, vectors
36+
// and iterators translated to pointers, unless they have a destructor, which
37+
// is called with a pointer to them.
38+
bool CanUnbox(clang::ASTContext &ctx, const clang::VarDecl *decl) {
3939
auto type = decl->getType();
4040
if (IsFlatVec(type)) {
4141
// Vectors are flat Vecs.
@@ -44,7 +44,8 @@ bool CanUnbox(const clang::VarDecl *decl) {
4444
return false;
4545
}
4646
} else if (type->isStructureOrClassType()) {
47-
if ((!IsUserDefinedDecl(type->getAsRecordDecl()) && !IsUniquePtr(type)) ||
47+
if ((!IsUserDefinedDecl(type->getAsRecordDecl()) && !IsUniquePtr(type) &&
48+
!RuleRegistry::MapsToRefcountPointer(ctx, type)) ||
4849
TypeNeedsDestruction(type)) {
4950
return false;
5051
}
@@ -194,7 +195,8 @@ class AddressTakenVisitor
194195

195196
private:
196197
// The arguments of a call translated by a rule are passed by value or
197-
// borrowed, unless the rule takes a pointer to them.
198+
// borrowed, unless the rule takes a pointer to them. A pointer parameter
199+
// receives the value of an argument that is itself translated to a pointer.
198200
void AddRuleArgs(clang::Expr *expr, clang::Expr **args, unsigned num_args) {
199201
auto *rule = RuleRegistry::GetExprRule(ctx_, expr);
200202
if (!rule) {
@@ -203,8 +205,10 @@ class AddressTakenVisitor
203205
// Variadic arguments are not considered.
204206
auto all_args = BuildUnifiedArgs(expr, args, num_args);
205207
for (unsigned i = 0; i < all_args.size() && i < rule->params.size(); ++i) {
206-
if (!rule->params[i].is_pointer()) {
207-
AddValueUse(IgnoreNoOpCasts(all_args[i]));
208+
auto *arg = IgnoreNoOpCasts(all_args[i]);
209+
if (!rule->params[i].is_pointer() || arg->getType()->isPointerType() ||
210+
RuleRegistry::MapsToPointer(ctx_, arg->getType())) {
211+
AddValueUse(arg);
208212
}
209213
}
210214
}
@@ -213,7 +217,14 @@ class AddressTakenVisitor
213217
// without making a pointer to it.
214218
void AddValueUse(clang::Expr *expr, bool write = false) {
215219
expr = expr->IgnoreParens();
216-
if (auto *member = clang::dyn_cast<clang::MemberExpr>(expr)) {
220+
// The value of a conditional lvalue is the value of either operand; it is
221+
// written through a pointer to the operand.
222+
if (auto *cond = clang::dyn_cast<clang::ConditionalOperator>(expr)) {
223+
if (!write) {
224+
AddValueUse(cond->getTrueExpr());
225+
AddValueUse(cond->getFalseExpr());
226+
}
227+
} else if (auto *member = clang::dyn_cast<clang::MemberExpr>(expr)) {
217228
auto *field = clang::dyn_cast<clang::FieldDecl>(member->getMemberDecl());
218229
// A union member is accessed through a pointer to the union.
219230
if (!member->isArrow() && field && !field->getParent()->isUnion()) {
@@ -244,7 +255,7 @@ class AddressTakenVisitor
244255

245256
void AddressTaken(const clang::ValueDecl *decl) {
246257
if (auto *var = clang::dyn_cast<clang::VarDecl>(decl);
247-
var && CanUnbox(var)) {
258+
var && CanUnbox(ctx_, var)) {
248259
address_taken_.insert(var);
249260
}
250261
}
@@ -256,13 +267,13 @@ class AddressTakenVisitor
256267
};
257268
} // namespace
258269

259-
BoxedVars::BoxedVars(clang::ASTContext &ctx) {
270+
BoxedVars::BoxedVars(clang::ASTContext &ctx) : ctx_(ctx) {
260271
AddressTakenVisitor(ctx, address_taken_)
261272
.TraverseDecl(ctx.getTranslationUnitDecl());
262273
}
263274

264275
bool BoxedVars::contains(const clang::VarDecl *decl) const {
265-
return !CanUnbox(decl) || address_taken_.contains(decl);
276+
return !CanUnbox(ctx_, decl) || address_taken_.contains(decl);
266277
}
267278

268279
namespace {

‎cpp2rust/converter/models/boxed_vars.h‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,17 @@ namespace cpp2rust {
1616
// to a function, or captured by a lambda. Any use that doesn't just read or
1717
// write the value of a variable is taken to make a pointer to it.
1818
//
19-
// Only scalars, arrays and user-defined structs are stored directly; other
20-
// variables are always boxed.
19+
// Only scalars, arrays, user-defined structs, unique_ptrs, vectors and
20+
// iterators translated to pointers are stored directly; other variables are
21+
// always boxed.
2122
class BoxedVars {
2223
public:
2324
explicit BoxedVars(clang::ASTContext &ctx);
2425

2526
bool contains(const clang::VarDecl *decl) const;
2627

2728
private:
29+
clang::ASTContext &ctx_;
2830
std::unordered_set<const clang::VarDecl *> address_taken_;
2931
};
3032

‎tests/unit/out/refcount/elidable_iterator_copy_cxx11.rs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ fn main_0() -> i32 {
2020
let __a1 = 7;
2121
(*v.borrow_mut()).push(__a1)
2222
};
23-
let it: Value<Ptr<i32>> = Rc::new(RefCell::new({
23+
let mut it: Ptr<i32> = {
2424
let count = ((v.as_pointer() as Ptr<i32>).to_end().get_offset()
2525
- (v.as_pointer() as Ptr<i32>).get_offset()) as usize;
2626
(v.as_pointer() as Ptr<i32>).offset(
@@ -31,9 +31,9 @@ fn main_0() -> i32 {
3131
.position(|value_0| value_0.read() == 7)
3232
.unwrap_or(count) as isize,
3333
)
34-
}));
35-
assert!((*it.borrow()) != (v.as_pointer() as Ptr<i32>).to_end());
36-
assert!((((*it.borrow()).read()) == 7));
34+
};
35+
assert!(it != (v.as_pointer() as Ptr<i32>).to_end());
36+
assert!(((it.read()) == 7));
3737
return 0;
3838
}
3939
pub fn __cpp2rust_init_globals() {}

‎tests/unit/out/refcount/find.rs‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ fn main_0() -> i32 {
2424
let __a1 = 3;
2525
(*v.borrow_mut()).push(__a1)
2626
};
27-
let v_begin: Value<Ptr<i32>> = Rc::new(RefCell::new((v.as_pointer() as Ptr<i32>)));
28-
let v_end: Value<Ptr<i32>> = Rc::new(RefCell::new((v.as_pointer() as Ptr<i32>).to_end()));
29-
let it: Value<Ptr<i32>> = Rc::new(RefCell::new({
30-
let count = ((*v_end.borrow()).get_offset() - (*v_begin.borrow()).get_offset()) as usize;
31-
(*v_begin.borrow()).offset(
32-
(*v_begin.borrow())
27+
let mut v_begin: Ptr<i32> = (v.as_pointer() as Ptr<i32>);
28+
let mut v_end: Ptr<i32> = (v.as_pointer() as Ptr<i32>).to_end();
29+
let mut it: Ptr<i32> = {
30+
let count = (v_end.get_offset() - v_begin.get_offset()) as usize;
31+
v_begin.offset(
32+
v_begin
3333
.clone()
3434
.into_iter()
3535
.take(count)
3636
.position(|value_0| value_0.read() == 2)
3737
.unwrap_or(count) as isize,
3838
)
39-
}));
40-
let mut v_result_true: bool = (*it.borrow()) != (v.as_pointer() as Ptr<i32>).to_end();
39+
};
40+
let mut v_result_true: bool = it != (v.as_pointer() as Ptr<i32>).to_end();
4141
let m: Value<BTreeMap<i32, Value<(Value<i32>, Value<f64>)>>> =
4242
Rc::new(RefCell::new(BTreeMap::new()));
4343
(m.as_pointer() as Ptr<BTreeMap<i32, Value<(Value<i32>, Value<f64>)>>>)

‎tests/unit/out/refcount/iterator_freshness.rs‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ use std::io::prelude::*;
66
use std::io::{Read, Seek, Write};
77
use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
9-
pub fn foo_0(a0: Ptr<i32>) {
10-
let a0: Value<Ptr<i32>> = Rc::new(RefCell::new(a0));
11-
}
9+
pub fn foo_0(mut a0: Ptr<i32>) {}
1210
pub fn main() {
1311
__cpp2rust_init_globals();
1412
std::process::exit(main_0());
@@ -19,8 +17,8 @@ fn main_0() -> i32 {
1917
.map(|_| <i32>::default())
2018
.collect::<Vec<_>>(),
2119
));
22-
let it: Value<Ptr<i32>> = Rc::new(RefCell::new((vec_.as_pointer() as Ptr<i32>)));
23-
({ foo_0((*it.borrow()).clone()) });
20+
let mut it: Ptr<i32> = (vec_.as_pointer() as Ptr<i32>);
21+
({ foo_0((it).clone()) });
2422
return 0;
2523
}
2624
pub fn __cpp2rust_init_globals() {}

‎tests/unit/out/refcount/reference_wrapper.rs‎

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@ pub struct Point {
1414
#[offset(4)]
1515
pub y: i32,
1616
}
17-
pub fn set_0(ref_: Ptr<i32>, mut val: i32) {
18-
let ref_: Value<Ptr<i32>> = Rc::new(RefCell::new(ref_));
19-
(*ref_.borrow()).write(val);
17+
pub fn set_0(mut ref_: Ptr<i32>, mut val: i32) {
18+
ref_.write(val);
2019
}
21-
pub fn read_1(ref_: Ptr<i32>) -> i32 {
22-
let ref_: Value<Ptr<i32>> = Rc::new(RefCell::new(ref_));
23-
let r: Ptr<i32> = (*ref_.borrow()).clone();
20+
pub fn read_1(mut ref_: Ptr<i32>) -> i32 {
21+
let r: Ptr<i32> = (ref_).clone();
2422
return (r.read());
2523
}
2624
pub fn main() {
@@ -29,36 +27,36 @@ pub fn main() {
2927
}
3028
fn main_0() -> i32 {
3129
let i1: Value<i32> = Rc::new(RefCell::new(10));
32-
let ref_1: Value<Ptr<i32>> = Rc::new(RefCell::new(i1.as_pointer()));
33-
(*ref_1.borrow()).write(20);
34-
let i2: Ptr<i32> = (*ref_1.borrow()).clone();
30+
let mut ref_1: Ptr<i32> = i1.as_pointer();
31+
ref_1.write(20);
32+
let i2: Ptr<i32> = (ref_1).clone();
3533
{
3634
i2.with_mut(|__v| *__v = *__v + 5)
3735
};
3836
write!(libcc2rs::cout(), "{:}\n", (*i1.borrow()),);
3937
let i3: Value<i32> = Rc::new(RefCell::new(1));
4038
let i4: Value<i32> = Rc::new(RefCell::new(2));
41-
let ref_3: Value<Ptr<i32>> = Rc::new(RefCell::new(i3.as_pointer()));
42-
let ref_4: Value<Ptr<i32>> = Rc::new(RefCell::new(i4.as_pointer()));
43-
let __rhs = ((*ref_4.borrow()).read());
44-
(*ref_3.borrow()).write(__rhs);
39+
let mut ref_3: Ptr<i32> = i3.as_pointer();
40+
let mut ref_4: Ptr<i32> = i4.as_pointer();
41+
let __rhs = (ref_4.read());
42+
ref_3.write(__rhs);
4543
write!(
4644
libcc2rs::cout(),
4745
"{:} {:}\n",
4846
(*i3.borrow()),
4947
(*i4.borrow()),
5048
);
51-
({ set_0((*ref_1.borrow()).clone(), 99) });
49+
({ set_0((ref_1).clone(), 99) });
5250
write!(
5351
libcc2rs::cout(),
5452
"{:} {:}\n",
5553
(*i1.borrow()),
56-
({ read_1((*ref_1.borrow()).clone(),) }),
54+
({ read_1((ref_1).clone(),) }),
5755
);
5856
let point: Value<Point> = Rc::new(RefCell::new(Point { x: 3, y: 4 }));
59-
let point_ref: Value<Ptr<Point>> = Rc::new(RefCell::new(point.as_pointer()));
60-
field!((*point_ref.borrow()), x).write(30);
61-
field!((*point_ref.borrow()), y).write(40);
57+
let mut point_ref: Ptr<Point> = point.as_pointer();
58+
field!(point_ref, x).write(30);
59+
field!(point_ref, y).write(40);
6260
write!(libcc2rs::cout(), "{:} {:}\n", { (*point.borrow()).x }, {
6361
(*point.borrow()).y
6462
},);

‎tests/unit/out/refcount/return_move.rs‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,11 @@ thread_local!(
3030
pub fn id_1(mut n: Ptr<node>) -> Ptr<node> {
3131
return n;
3232
}
33-
pub fn pick_2(a: Ptr<node>, b: Ptr<node>) -> Ptr<node> {
34-
let a: Value<Ptr<node>> = Rc::new(RefCell::new(a));
35-
let b: Value<Ptr<node>> = Rc::new(RefCell::new(b));
36-
return if !(*a.borrow()).is_null() {
37-
(*a.borrow()).clone()
33+
pub fn pick_2(mut a: Ptr<node>, mut b: Ptr<node>) -> Ptr<node> {
34+
return if !(a).is_null() {
35+
(a).clone()
3836
} else {
39-
(*b.borrow()).clone()
37+
(b).clone()
4038
};
4139
}
4240
pub fn local_ptr_3(mut n: Ptr<node>) -> Ptr<node> {

‎tests/unit/out/refcount/split_binop_aliased_borrows.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ pub fn main() {
1212
}
1313
fn main_0() -> i32 {
1414
let v: Value<Vec<i32>> = Rc::new(RefCell::new(vec![1, 2]));
15-
let p: Value<Ptr<i32>> = Rc::new(RefCell::new((v.as_pointer() as Ptr<i32>)));
15+
let mut p: Ptr<i32> = (v.as_pointer() as Ptr<i32>);
1616
let r: Ptr<i32> = (v.as_pointer() as Ptr<i32>).offset(1_usize);
1717
let __rhs = (r.read());
18-
(*p.borrow()).write(__rhs);
18+
p.write(__rhs);
1919
assert!(({ (*v.borrow())[0_usize] } == 2));
2020
return 0;
2121
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
pub fn median_0(mut w: i32, mut n: i32, mut nw: i32) -> i32 {
10+
let mut mx: i32 = if (w > n) { w } else { n };
11+
let mut mn: i32 = ((w + n) - mx);
12+
if (nw > mx) {
13+
return mn;
14+
} else if (nw < mn) {
15+
return mx;
16+
}
17+
return ((n + w) - nw);
18+
}
19+
pub fn assign_1(mut c: bool, mut v: i32) -> i32 {
20+
let a: Value<i32> = Rc::new(RefCell::new(1));
21+
let b: Value<i32> = Rc::new(RefCell::new(2));
22+
if c {
23+
(a.as_pointer())
24+
} else {
25+
(b.as_pointer())
26+
}
27+
.write(v);
28+
if c {
29+
(a.as_pointer())
30+
} else {
31+
(b.as_pointer())
32+
}
33+
.with_mut(|__v| __v.prefix_inc());
34+
return (((*a.borrow()) * 10) + (*b.borrow()));
35+
}
36+
pub fn lehmer_2(mut sigma: Ptr<u32>, mut len: u32, mut code: Ptr<u32>) {
37+
let items: Value<Vec<u32>> = Rc::new(RefCell::new(
38+
(0..(len as usize) as usize)
39+
.map(|_| <u32>::default())
40+
.collect::<Vec<_>>(),
41+
));
42+
let mut i: u32 = 0_u32;
43+
'loop_: while (i < len) {
44+
let __rhs = i;
45+
(*items.borrow_mut())[(i as usize)] = __rhs;
46+
i.prefix_inc();
47+
}
48+
let mut i: u32 = 0_u32;
49+
'loop_: while (i < len) {
50+
let mut it: Ptr<u32> = {
51+
let count = ((items.as_pointer() as Ptr<u32>).to_end().get_offset()
52+
- (items.as_pointer() as Ptr<u32>).get_offset()) as usize;
53+
(items.as_pointer() as Ptr<u32>).offset(
54+
(items.as_pointer() as Ptr<u32>)
55+
.clone()
56+
.into_iter()
57+
.take(count)
58+
.position(|value_0| value_0.read() == (elem!(sigma, i).read()))
59+
.unwrap_or(count) as isize,
60+
)
61+
};
62+
assert!(it != (items.as_pointer() as Ptr<u32>).to_end());
63+
let __rhs = (((it.get_offset() as isize)
64+
- ((items.as_pointer() as Ptr<u32>).get_offset() as isize))
65+
as u32);
66+
elem!(code, i).write(__rhs);
67+
{
68+
let idx = it.get_offset();
69+
(items.as_pointer() as Ptr<Vec<u32>>).with_mut(|__v: &mut Vec<u32>| __v.remove(idx));
70+
(items.as_pointer() as Ptr<Vec<u32>>).decay()
71+
};
72+
i.prefix_inc();
73+
}
74+
}
75+
pub fn sum_3(v: Ptr<Vec<i32>>) -> i32 {
76+
let mut s: i32 = 0;
77+
let mut it: Ptr<i32> = (Ptr::<Vec<i32>>::decay(&(v)) as Ptr<i32>);
78+
'loop_: while it != (Ptr::<Vec<i32>>::decay(&(v)) as Ptr<i32>).to_end() {
79+
s += (it.read());
80+
it.prefix_inc();
81+
}
82+
return s;
83+
}
84+
pub fn main() {
85+
__cpp2rust_init_globals();
86+
std::process::exit(main_0());
87+
}
88+
fn main_0() -> i32 {
89+
assert!((({ median_0(1, 5, 7,) }) == 1));
90+
assert!((({ median_0(1, 5, 0,) }) == 5));
91+
assert!((({ median_0(1, 5, 3,) }) == 3));
92+
assert!((({ assign_1(true, 5,) }) == 62));
93+
assert!((({ assign_1(false, 5,) }) == 16));
94+
let sigma: Value<Box<[u32]>> = Rc::new(RefCell::new(Box::new([2_u32, 0_u32, 3_u32, 1_u32])));
95+
let code: Value<Box<[u32]>> =
96+
Rc::new(RefCell::new((0..4).map(|_| 0_u32).collect::<Box<[u32]>>()));
97+
({
98+
lehmer_2(
99+
(sigma.as_pointer() as Ptr<u32>),
100+
4_u32,
101+
(code.as_pointer() as Ptr<u32>),
102+
)
103+
});
104+
assert!(
105+
((((*code.borrow())[(0) as usize] == 2_u32) && ((*code.borrow())[(1) as usize] == 0_u32))
106+
&& ((*code.borrow())[(2) as usize] == 1_u32))
107+
&& ((*code.borrow())[(3) as usize] == 0_u32)
108+
);
109+
let v: Value<Vec<i32>> = Rc::new(RefCell::new(vec![1, 2, 3]));
110+
assert!((({ sum_3(v.as_pointer(),) }) == 6));
111+
return 0;
112+
}
113+
pub fn __cpp2rust_init_globals() {}

0 commit comments

Comments
 (0)