Skip to content

Commit 6485b0a

Browse files
authored
Remove unneeded clones in converter and rules (#371)
This PR removes unneeded clones **in converter** by calling `SetValueFreshness`/`computed_expr_type_`/`SetFreshType` on every fressh-value-producing path. It asserts that `computed_expr_type_` is not Unknown after a conversion to make sure that we did not miss any path. PendingDeref carries freshness separately. Producers of PendingDeref set freshness and consumers act based on that. I also added `ComputedExprType::Pending` because freshness is unknown until the consumer of PendingDeref sets it. This PR also removes unneeded clones **in rules** using the `Access` IR attribute. Rules no longer clone their arguments. The preprocessor infers how each argument is used: `borrow, borrow_mut, move, take`. A `move` (`let s = a0`) consumes the argument, and it's cloned if it's not already fresh. A `borrow` usage (`a0.len()`) is never cloned. Besides removing unneeded clones, on the converter side, this fixes #363. On the rules side, `rule-preprocessor` infers the access type of each argument automatically instead on relying on the rule author to encode it properly. This caught a bug in `std::vector::push_back(T&&)`: the rule argument took the argument by value and cloned it, instead of moving it.
1 parent f174541 commit 6485b0a

85 files changed

Lines changed: 593 additions & 429 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎cpp2rust/converter/converter.cpp‎

Lines changed: 88 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,13 @@ bool Converter::RecordDerivesDefault(const clang::RecordDecl *decl) {
681681
return true;
682682
}
683683

684+
bool Converter::IsPassThroughRule(clang::Expr *expr) const {
685+
const auto *rule = Mapper::GetExprRule(GetCalleeOrExpr(expr));
686+
return rule && rule->body.size() == 1 &&
687+
std::holds_alternative<TranslationRule::PlaceholderFragment>(
688+
rule->body[0]);
689+
}
690+
684691
bool Converter::RecordDerivesCopy(const clang::RecordDecl *decl) const {
685692
auto *derives = Mapper::MappedDerives(ctx_.getCanonicalTagType(decl));
686693
return derives &&
@@ -1491,7 +1498,12 @@ bool Converter::Convert(clang::Expr *expr,
14911498
NeedsImplicitScalarCast(expr->IgnoreImplicit()->getType(),
14921499
*implicit_convert_to);
14931500
PushParen paren(*this, needs_conversion);
1501+
computed_expr_type_ = ComputedExprType::Unknown;
14941502
bool result = TraverseStmt(expr);
1503+
if (expr && computed_expr_type_ == ComputedExprType::Unknown) {
1504+
expr->dump();
1505+
assert(false && "computed_expr_type_ not set");
1506+
}
14951507
if (needs_conversion) {
14961508
ConvertCast(*implicit_convert_to);
14971509
computed_expr_type_ = ComputedExprType::FreshValue;
@@ -1721,17 +1733,20 @@ void Converter::ConvertVAArgCall(clang::CallExpr *expr) {
17211733
bool Converter::VisitCallExpr(clang::CallExpr *expr) {
17221734
if (IsBuiltinVaStart(expr) || IsBuiltinVaEnd(expr) || IsBuiltinVaCopy(expr)) {
17231735
ConvertVAArgCall(expr);
1736+
SetFreshType(expr->getType());
17241737
return false;
17251738
}
17261739

17271740
// p->~T() on a scalar is a no-op
17281741
if (clang::isa<clang::CXXPseudoDestructorExpr>(
17291742
expr->getCallee()->IgnoreParenImpCasts())) {
1743+
SetFreshType(expr->getType());
17301744
return false;
17311745
}
17321746

17331747
if (auto plugin_str = TryPluginConvert(expr)) {
17341748
StrCat(*plugin_str);
1749+
SetFreshType(expr->getType());
17351750
return false;
17361751
}
17371752

@@ -1750,9 +1765,10 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) {
17501765
str = GetMappedAsString(expr, args, num_args, &ctx);
17511766
};
17521767

1753-
if ((IsReferenceType(expr) ||
1754-
GetReturnTypeOfFunction(expr)->isReferenceType()) &&
1755-
!isAddrOf() && !isVoid()) {
1768+
bool deref_ref = (IsReferenceType(expr) ||
1769+
GetReturnTypeOfFunction(expr)->isReferenceType()) &&
1770+
!isAddrOf() && !isVoid();
1771+
if (deref_ref) {
17561772
str = "( * " + std::move(str) + " )";
17571773
}
17581774

@@ -1761,6 +1777,11 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) {
17611777
}
17621778

17631779
StrCat(str);
1780+
if (deref_ref) {
1781+
SetValueFreshness(expr->getType());
1782+
} else if (!IsPassThroughRule(expr)) {
1783+
SetFreshType(expr->getType());
1784+
}
17641785
return false;
17651786
}
17661787

@@ -1795,6 +1816,7 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) {
17951816
}
17961817

17971818
StrCat(str);
1819+
SetFreshType(expr->getType());
17981820
return false;
17991821
}
18001822

@@ -1809,6 +1831,7 @@ void Converter::EmitFnPtrCall(clang::Expr *callee) {
18091831
void Converter::ConvertFunctionToFunctionPointer(
18101832
const clang::FunctionDecl *fn_decl) {
18111833
StrCat(std::format("Some({})", Mapper::MapFunctionName(fn_decl)));
1834+
computed_expr_type_ = ComputedExprType::FreshPointer;
18121835
}
18131836

18141837
Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
@@ -2256,6 +2279,7 @@ void Converter::ConvertIntegerToEnumeralCast(clang::Expr *to,
22562279
auto dst_enum = to->getType()->getAs<clang::EnumType>();
22572280
if (src_enum && dst_enum && dst_enum->getDecl() == src_enum) {
22582281
StrCat(EnumeratorName(ec));
2282+
computed_expr_type_ = ComputedExprType::FreshValue;
22592283
return;
22602284
}
22612285
}
@@ -2266,6 +2290,7 @@ void Converter::ConvertIntegerToEnumeralCast(clang::Expr *to,
22662290
Convert(from);
22672291
}
22682292
StrCat(keyword::kAs, GetUnsafeTypeAsString(to->getType()));
2293+
computed_expr_type_ = ComputedExprType::FreshValue;
22692294
}
22702295

22712296
void Converter::ConvertIntegralToBooleanCast(clang::ImplicitCastExpr *expr) {
@@ -2285,6 +2310,7 @@ void Converter::ConvertIntegralToBooleanCast(clang::ImplicitCastExpr *expr) {
22852310
Convert(sub_expr);
22862311
StrCat(token::kDiff);
22872312
StrCat(token::kZero);
2313+
computed_expr_type_ = ComputedExprType::FreshValue;
22882314
}
22892315

22902316
bool Converter::IsCastRedundantInRust(clang::Expr *expr,
@@ -2323,6 +2349,7 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
23232349
} else {
23242350
StrCat(dest_pointee_const ? ".as_ptr()" : ".as_mut_ptr()");
23252351
}
2352+
computed_expr_type_ = ComputedExprType::FreshPointer;
23262353
break;
23272354
}
23282355
case clang::CastKind::CK_BitCast: {
@@ -2334,6 +2361,7 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
23342361
StrCat(ConvertPointeeType(sub_expr->getType()));
23352362
}
23362363
ConvertCast(type);
2364+
SetFreshType(type);
23372365
break;
23382366
}
23392367
case clang::CastKind::CK_NoOp: {
@@ -2358,13 +2386,15 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
23582386
PushParen paren(*this);
23592387
Convert(sub_expr);
23602388
ConvertCast(type);
2389+
SetFreshType(type);
23612390
} else {
23622391
{
23632392
PushParen paren(*this, suffix);
23642393
Convert(sub_expr);
23652394
}
23662395
if (suffix) {
23672396
StrCat(suffix);
2397+
SetFreshType(type);
23682398
}
23692399
}
23702400
break;
@@ -2424,6 +2454,7 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
24242454
ConvertCast(type);
24252455
}
24262456
}
2457+
SetFreshType(type);
24272458
}
24282459
return false;
24292460
}
@@ -2714,6 +2745,7 @@ bool Converter::ConvertIncAndDec(clang::UnaryOperator *expr) {
27142745
bool Converter::VisitUnaryOperator(clang::UnaryOperator *expr) {
27152746
if (auto str = GetMappedAsString(expr); !str.empty()) {
27162747
StrCat(str);
2748+
SetFreshType(expr->getType());
27172749
return false;
27182750
}
27192751

@@ -2770,6 +2802,7 @@ bool Converter::VisitUnaryOperator(clang::UnaryOperator *expr) {
27702802
default:
27712803
StrCat(expr->getOpcodeStr(opcode));
27722804
Convert(sub_expr);
2805+
SetFreshType(expr->getType());
27732806
}
27742807
return false;
27752808
}
@@ -2882,6 +2915,9 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
28822915
ConvertFunctionToFunctionPointer(fn_decl);
28832916
return false;
28842917
}
2918+
StrCat(str);
2919+
SetFreshType(expr->getType());
2920+
return false;
28852921
}
28862922

28872923
if (auto var_decl = clang::dyn_cast<clang::VarDecl>(decl)) {
@@ -2891,6 +2927,7 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
28912927
init->IgnoreUnlessSpelledInSource())) {
28922928
PushParen paren(*this);
28932929
VisitLambdaExpr(lambda);
2930+
computed_expr_type_ = ComputedExprType::FreshValue;
28942931
return false;
28952932
}
28962933
}
@@ -2900,10 +2937,16 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
29002937
if (!decl->getType()->getAs<clang::ReferenceType>() && isAddrOf()) {
29012938
StrCat(token::kRef, decl->getType().isConstQualified() ? "" : keyword_mut_,
29022939
str);
2940+
computed_expr_type_ = ComputedExprType::FreshPointer;
29032941
return false;
29042942
}
29052943

29062944
StrCat(str);
2945+
if (clang::isa<clang::EnumConstantDecl>(decl)) {
2946+
computed_expr_type_ = ComputedExprType::FreshValue;
2947+
return false;
2948+
}
2949+
SetValueFreshness(expr->getType());
29072950
return false;
29082951
}
29092952

@@ -2996,6 +3039,7 @@ bool Converter::VisitMemberExpr(clang::MemberExpr *expr) {
29963039
SetUFCSReceiver(expr->getBase(), expr->isArrow(), method);
29973040
StrCat(GetRecordName(method->getParent()), token::kDoubleColon,
29983041
GetMethodName(method));
3042+
SetFreshType(expr->getType());
29993043
return false;
30003044
}
30013045
std::string str;
@@ -3029,10 +3073,16 @@ bool Converter::VisitMemberExpr(clang::MemberExpr *expr) {
30293073
if (!isAddrOf() && member->getType()->isFunctionPointerType()) {
30303074
PushParen paren(*this);
30313075
StrCat(str);
3076+
SetValueFreshness(expr->getType());
30323077
return false;
30333078
}
30343079

30353080
StrCat(str);
3081+
if (clang::isa<clang::CXXMethodDecl>(member)) {
3082+
SetFreshType(expr->getType());
3083+
} else {
3084+
SetValueFreshness(expr->getType());
3085+
}
30363086
return false;
30373087
}
30383088

@@ -3144,6 +3194,7 @@ bool Converter::VisitCXXThisExpr(clang::CXXThisExpr *expr) {
31443194
PushParen paren(*this);
31453195
StrCat(keyword::kSelfValue, keyword::kAs, ToString(expr->getType()));
31463196
}
3197+
computed_expr_type_ = ComputedExprType::FreshPointer;
31473198
return false;
31483199
}
31493200

@@ -3169,6 +3220,7 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) {
31693220
} else {
31703221
StrCat(GetArrayDefaultAsString(qual_type));
31713222
}
3223+
SetFreshType(qual_type);
31723224
return false;
31733225
}
31743226

@@ -3204,6 +3256,7 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) {
32043256
}
32053257
}
32063258
}
3259+
SetFreshType(qual_type);
32073260
return false;
32083261
}
32093262

@@ -3407,6 +3460,9 @@ bool Converter::VisitCXXConstructExpr(clang::CXXConstructExpr *expr) {
34073460
if (auto str = GetMappedAsString(expr, expr->getArgs(), expr->getNumArgs());
34083461
!str.empty()) {
34093462
StrCat(str);
3463+
if (!IsPassThroughRule(expr)) {
3464+
SetFreshType(expr->getType());
3465+
}
34103466
return false;
34113467
}
34123468

@@ -3428,13 +3484,15 @@ bool Converter::VisitCXXConstructExpr(clang::CXXConstructExpr *expr) {
34283484
if ((ctor->isCopyConstructor() || IsDefaultedMoveConstructor(ctor)) &&
34293485
!suppress && !TypeIsCopyable(expr->getType())) {
34303486
StrCat(".clone()");
3487+
SetFreshType(expr->getType());
34313488
}
34323489
return false;
34333490
}
34343491

34353492
if (ctor->isDefaultConstructor() && !ctor->isUserProvided()) {
34363493
auto ty = expr->getType();
34373494
StrCat(GetDefaultAsString(ty));
3495+
SetFreshType(expr->getType());
34383496
return false;
34393497
}
34403498

@@ -3444,6 +3502,7 @@ bool Converter::VisitCXXConstructExpr(clang::CXXConstructExpr *expr) {
34443502
} else {
34453503
ConvertCXXConstructExprArgs(expr);
34463504
}
3505+
SetFreshType(expr->getType());
34473506
return false;
34483507
}
34493508

@@ -3541,6 +3600,12 @@ bool Converter::VisitCXXDefaultArgExpr(clang::CXXDefaultArgExpr *expr) {
35413600
return false;
35423601
}
35433602

3603+
bool Converter::VisitConstantExpr(clang::ConstantExpr *expr) {
3604+
Convert(expr->getSubExpr());
3605+
SetFreshType(expr->getType());
3606+
return false;
3607+
}
3608+
35443609
bool Converter::VisitLambdaExpr(clang::LambdaExpr *expr) {
35453610
if (isAddrOf() && expr->capture_size() == 0) {
35463611
StrCat("Some");
@@ -4477,13 +4542,15 @@ void Converter::ConvertAddrOf(clang::Expr *expr, clang::QualType pointer_type) {
44774542
: keyword_mut_);
44784543
Convert(expr);
44794544
ConvertCast(pointer_type);
4545+
computed_expr_type_ = ComputedExprType::FreshPointer;
44804546
} else {
44814547
StrCat(token::kRef);
44824548
if (!pointer_type->getPointeeType().isConstQualified()) {
44834549
StrCat(keyword_mut_);
44844550
}
44854551
Convert(expr);
44864552
ConvertCast(pointer_type);
4553+
computed_expr_type_ = ComputedExprType::FreshPointer;
44874554
}
44884555
}
44894556

@@ -4495,6 +4562,7 @@ void Converter::EmitDeref(std::string inner, clang::QualType pointee_type) {
44954562
}
44964563
PushParen paren(*this);
44974564
StrCat(GetPointerDerefPrefix(pointee_type), std::move(inner));
4565+
SetValueFreshness(pointee_type);
44984566
}
44994567

45004568
void Converter::ConvertDeref(clang::Expr *expr) {
@@ -4555,8 +4623,8 @@ void Converter::PlaceholderCtx::dump() const {
45554623
<< ", is_cpp_ptr: " << is_cpp_ptr
45564624
<< ", maps_to_rust_ptr: " << maps_to_rust_ptr
45574625
<< ", declared_in_rule_as_rust_ptr: "
4558-
<< declared_in_rule_as_rust_ptr << ", access: "
4559-
<< (access == TranslationRule::Access::kRead ? "read" : "write")
4626+
<< declared_in_rule_as_rust_ptr
4627+
<< ", access: " << static_cast<int>(access)
45604628
<< ", param_type: " << param_type
45614629
<< ", materialize_idx: " << materialize_idx << '\n';
45624630
}
@@ -4594,10 +4662,10 @@ std::string Converter::ConvertPlaceholder(clang::Expr *expr, clang::Expr *arg,
45944662
if (ph_ctx.needs_object_receiver()) {
45954663
Buffer buf(*this);
45964664
PushExplicitAutoref autoref(
4597-
*this,
4598-
ph_ctx.is_index_base
4599-
? std::optional(ph_ctx.access == TranslationRule::Access::kWrite)
4600-
: std::nullopt);
4665+
*this, ph_ctx.is_index_base
4666+
? std::optional(ph_ctx.access ==
4667+
TranslationRule::Access::kBorrowMut)
4668+
: std::nullopt);
46014669
PushExprKind push(*this, ExprKind::RValue);
46024670
ConvertDeref(arg);
46034671
return std::move(buf).str();
@@ -4611,13 +4679,17 @@ std::string Converter::ConvertPlaceholder(clang::Expr *expr, clang::Expr *arg,
46114679
return ConvertLValue(arg);
46124680
}
46134681

4614-
if (ph_ctx.access == TranslationRule::Access::kMove) {
4682+
if (ph_ctx.access == TranslationRule::Access::kTake) {
46154683
if (clang::isa<clang::MaterializeTemporaryExpr>(arg)) {
46164684
return ConvertRValue(arg);
46174685
}
46184686
return std::format("std::mem::take(&mut {})", ConvertLValue(arg));
46194687
}
46204688

4689+
if (ph_ctx.access == TranslationRule::Access::kMove) {
4690+
return ConvertFreshRValue(arg, ph_ctx.implicit_convert_to);
4691+
}
4692+
46214693
return ConvertRValue(arg, ph_ctx.implicit_convert_to);
46224694
}
46234695

@@ -4774,6 +4846,12 @@ void Converter::SetFresh() {
47744846
case ComputedExprType::FreshValue:
47754847
case ComputedExprType::FreshPointer:
47764848
break;
4849+
case ComputedExprType::Unknown:
4850+
assert(0 && "Unreachable ComputedExprType::Unknown");
4851+
break;
4852+
case ComputedExprType::Pending:
4853+
assert(0 && "Unreachable ComputedExprType::Pending");
4854+
break;
47774855
}
47784856
}
47794857

0 commit comments

Comments
 (0)