Skip to content

Commit 6564505

Browse files
Copilotnunoplopes
andauthored
perf: eliminate spurious string copies in cpp2rust converter
- mapper.cpp: use std::move() when passing local strings to normalizeTranslationRule() to avoid unnecessary copies in ToString() - converter.cpp recordDerivesCopy: cache Mapper::Map(f->getType()) result to avoid calling it twice per field - converter.cpp GetDefaultAsString: cache Mapper::ToString(qual_type) result to avoid calling it twice in successive else-if branches - converter.cpp EmitRustStruct/VisitCXXRecordDecl: replace std::string(keyword::kImpl) + ' ' + name with std::format to avoid constructing multiple temporary strings - converter_lib.cpp GetFileName: construct std::filesystem::path directly from StringRef iterators, eliminating the intermediate file_name_as_string copy and reusing file_path.string() as fallback Agent-Logs-Url: https://github.com/Cpp2Rust/cpp2rust/sessions/b538d15a-35a7-4c43-93f3-6621eabaf105 Co-authored-by: nunoplopes <2998477+nunoplopes@users.noreply.github.com>
1 parent 9802d0a commit 6564505

3 files changed

Lines changed: 45 additions & 42 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -552,15 +552,16 @@ static bool recordDerivesCopy(const clang::RecordDecl *decl) {
552552
for (auto f : decl->fields()) {
553553
// Records that contain std::vector, std::array, std::string or anything
554554
// that is translated to Vec<>, do not derive Copy
555-
if (Mapper::Map(f->getType()).starts_with("Vec<")) {
555+
auto mapped = Mapper::Map(f->getType());
556+
if (mapped.starts_with("Vec<")) {
556557
return false;
557558
}
558559

559560
if (IsUniquePtr(f->getType())) {
560561
return false;
561562
}
562563

563-
if (Mapper::Map(f->getType()).starts_with("BTreeMap<")) {
564+
if (mapped.starts_with("BTreeMap<")) {
564565
return false;
565566
}
566567

@@ -652,7 +653,7 @@ void Converter::EmitRustStruct(clang::RecordDecl *decl) {
652653
auto struct_name = GetRecordName(cxx);
653654

654655
ConvertCXXMethodDecls(
655-
cxx, std::string(keyword::kImpl) + ' ' + struct_name,
656+
cxx, std::format("{} {}", keyword::kImpl, struct_name),
656657
[](const auto *method) {
657658
return !method->isImplicit() &&
658659
!(method->getDefinition() &&
@@ -700,7 +701,7 @@ bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
700701
if (decl->isStruct() || decl->isClass()) {
701702
for (auto c : GetTemplateInstantiatedCtors(decl)) {
702703
if (!decl_ids_.contains(GetID(c))) {
703-
StrCat(std::string(keyword::kImpl) + ' ' + GetRecordName(decl),
704+
StrCat(std::format("{} {}", keyword::kImpl, GetRecordName(decl)),
704705
token::kOpenCurlyBracket);
705706
VisitCXXMethodDecl(c);
706707
StrCat(token::kCloseCurlyBracket);
@@ -2745,40 +2746,43 @@ std::string Converter::GetDefaultAsString(clang::QualType qual_type) {
27452746
} else if (auto *array_type =
27462747
clang::dyn_cast<clang::IncompleteArrayType>(qual_type)) {
27472748
return GetDefaultAsString(array_type->getElementType());
2748-
} else if (Mapper::ToString(qual_type) == "struct std::pair") {
2749-
auto template_args = *GetTemplateArgs(qual_type);
2750-
auto first_type = template_args[0].getAsType();
2751-
auto second_type = template_args[1].getAsType();
2752-
return std::format("({}, {})", GetDefaultAsString(first_type),
2753-
GetDefaultAsString(second_type));
2754-
} else if (Mapper::ToString(qual_type).contains("std::array")) {
2755-
assert(GetTemplateArgs(qual_type).has_value());
2756-
auto template_args = *GetTemplateArgs(qual_type);
2757-
assert(template_args.size() == 2);
2758-
auto array_size = template_args[1];
2759-
unsigned size = 0;
2760-
switch (array_size.getKind()) {
2761-
case clang::TemplateArgument::Expression: {
2762-
auto array_size_expr = array_size.getAsExpr();
2763-
assert(array_size_expr && !array_size_expr->isValueDependent());
2764-
clang::Expr::EvalResult result;
2765-
ENSURE(array_size_expr->EvaluateAsInt(result, ctx_));
2766-
size = result.Val.getInt().getZExtValue();
2767-
break;
2768-
}
2769-
case clang::TemplateArgument::Integral: {
2770-
size = array_size.getAsIntegral().getZExtValue();
2771-
break;
2772-
}
2773-
default:
2774-
assert(0 && "Unsupported array size kind");
2775-
break;
2776-
}
2777-
return std::format(
2778-
"std::array::from_fn::<_, {}, _>(|_| Default::default()).to_vec()",
2779-
size);
27802749
} else {
2781-
return GetDefaultAsStringFallback(qual_type);
2750+
auto qual_type_str = Mapper::ToString(qual_type);
2751+
if (qual_type_str == "struct std::pair") {
2752+
auto template_args = *GetTemplateArgs(qual_type);
2753+
auto first_type = template_args[0].getAsType();
2754+
auto second_type = template_args[1].getAsType();
2755+
return std::format("({}, {})", GetDefaultAsString(first_type),
2756+
GetDefaultAsString(second_type));
2757+
} else if (qual_type_str.contains("std::array")) {
2758+
assert(GetTemplateArgs(qual_type).has_value());
2759+
auto template_args = *GetTemplateArgs(qual_type);
2760+
assert(template_args.size() == 2);
2761+
auto array_size = template_args[1];
2762+
unsigned size = 0;
2763+
switch (array_size.getKind()) {
2764+
case clang::TemplateArgument::Expression: {
2765+
auto array_size_expr = array_size.getAsExpr();
2766+
assert(array_size_expr && !array_size_expr->isValueDependent());
2767+
clang::Expr::EvalResult result;
2768+
ENSURE(array_size_expr->EvaluateAsInt(result, ctx_));
2769+
size = result.Val.getInt().getZExtValue();
2770+
break;
2771+
}
2772+
case clang::TemplateArgument::Integral: {
2773+
size = array_size.getAsIntegral().getZExtValue();
2774+
break;
2775+
}
2776+
default:
2777+
assert(0 && "Unsupported array size kind");
2778+
break;
2779+
}
2780+
return std::format(
2781+
"std::array::from_fn::<_, {}, _>(|_| Default::default()).to_vec()",
2782+
size);
2783+
} else {
2784+
return GetDefaultAsStringFallback(qual_type);
2785+
}
27822786
}
27832787
}
27842788

cpp2rust/converter/converter_lib.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,11 +267,10 @@ std::string GetFileName(const clang::Decl *decl) {
267267
const auto &ctx = decl->getASTContext();
268268
const auto full_location = ctx.getFullLoc(decl->getBeginLoc());
269269
const auto file_name = ctx.getSourceManager().getFilename(full_location);
270-
const auto file_name_as_string = file_name.str();
271-
const std::filesystem::path file_path(file_name_as_string);
270+
const std::filesystem::path file_path(file_name.begin(), file_name.end());
272271
return std::filesystem::exists(file_path)
273272
? std::filesystem::canonical(file_path).string()
274-
: file_name_as_string;
273+
: file_path.string();
275274
}
276275

277276
unsigned GetLineNumber(const clang::Decl *decl) {

cpp2rust/converter/mapper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ std::string ToString(clang::QualType qual_type) {
720720
std::string type;
721721
llvm::raw_string_ostream os(type);
722722
normalizeQualType(qual_type).print(os, getPrintPolicy());
723-
return normalizeTranslationRule(type);
723+
return normalizeTranslationRule(std::move(type));
724724
}
725725

726726
std::string ToString(const clang::NamedDecl *decl) {
@@ -736,7 +736,7 @@ std::string ToString(const clang::NamedDecl *decl) {
736736

737737
if (!func_decl) {
738738
decl->printQualifiedName(os, getPrintPolicy());
739-
return normalizeTranslationRule(out);
739+
return normalizeTranslationRule(std::move(out));
740740
}
741741

742742
os << ToString(func_decl->getReturnType()) << " ";

0 commit comments

Comments
 (0)