Skip to content

Commit 3959880

Browse files
Copilotnunoplopes
andauthored
Implement all code optimizations
Agent-Logs-Url: https://github.com/Cpp2Rust/cpp2rust/sessions/02781840-6bfd-443e-9a68-91ff30c2f21d Co-authored-by: nunoplopes <2998477+nunoplopes@users.noreply.github.com>
1 parent 235175d commit 3959880

3 files changed

Lines changed: 53 additions & 43 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,30 +1505,46 @@ void Converter::ConvertGenericCallExpr(clang::CallExpr *expr) {
15051505
? function->getNumParams()
15061506
: (proto ? proto->getNumParams() : num_args);
15071507

1508+
// Pre-compute per-parameter metadata once to avoid recomputing in two loops.
1509+
struct ParamInfo {
1510+
clang::Expr *arg;
1511+
std::string name;
1512+
clang::QualType type;
1513+
bool has_default_value;
1514+
};
1515+
const unsigned num_params_to_bind =
1516+
std::min<unsigned>(num_named_params, num_args);
1517+
std::vector<ParamInfo> param_infos;
1518+
param_infos.reserve(num_params_to_bind);
1519+
for (unsigned i = 0; i < num_params_to_bind; ++i) {
1520+
ParamInfo pi;
1521+
pi.arg = expr->getArg(i + arg_begin);
1522+
pi.name = function ? function->getParamDecl(i)->getNameAsString()
1523+
: ("arg" + std::to_string(i));
1524+
pi.type = function ? function->getParamDecl(i)->getType()
1525+
: proto->getParamType(i);
1526+
pi.has_default_value =
1527+
function && function->getParamDecl(i)->hasDefaultArg();
1528+
param_infos.push_back(std::move(pi));
1529+
}
1530+
15081531
// Track which args are materialized temps bound to reference params
15091532
std::vector<std::string> temp_refs(num_args);
15101533

1511-
for (unsigned i = 0; i < num_named_params && i < num_args; ++i) {
1512-
auto *arg = expr->getArg(i + arg_begin);
1513-
std::string param_name = function
1514-
? function->getParamDecl(i)->getNameAsString()
1515-
: ("arg" + std::to_string(i));
1516-
clang::QualType param_type = function ? function->getParamDecl(i)->getType()
1517-
: proto->getParamType(i);
1518-
1534+
for (unsigned i = 0; i < num_params_to_bind; ++i) {
1535+
auto &pi = param_infos[i];
15191536
bool is_materialize_to_ref =
1520-
clang::isa<clang::MaterializeTemporaryExpr>(arg) &&
1521-
param_type->isLValueReferenceType();
1537+
clang::isa<clang::MaterializeTemporaryExpr>(pi.arg) &&
1538+
pi.type->isLValueReferenceType();
15221539

15231540
if (is_materialize_to_ref) {
15241541
auto [binding, ref] =
1525-
MaterializeTemp(std::format("_{}", param_name), param_type, arg);
1542+
MaterializeTemp(std::format("_{}", pi.name), pi.type, pi.arg);
15261543
StrCat(binding);
15271544
temp_refs[i] = std::move(ref);
1528-
} else if (!clang::isa<clang::MaterializeTemporaryExpr>(arg)) {
1529-
StrCat("let", std::format("_{}: {}", param_name, ToString(param_type)),
1530-
"=");
1531-
convert_param_ty(param_type, arg);
1545+
} else if (!clang::isa<clang::MaterializeTemporaryExpr>(pi.arg)) {
1546+
StrCat("let", std::format("_{}: {}", pi.name, ToString(pi.type)), "=");
1547+
convert_param_ty(pi.type, pi.arg);
15321548
StrCat(";");
15331549
}
15341550
}
@@ -1541,28 +1557,19 @@ void Converter::ConvertGenericCallExpr(clang::CallExpr *expr) {
15411557
}
15421558
{
15431559
PushParen call_args(*this);
1544-
for (unsigned i = 0; i < num_named_params && i < num_args; ++i) {
1545-
auto *arg = expr->getArg(i + arg_begin);
1546-
std::string param_name =
1547-
function ? function->getParamDecl(i)->getNameAsString()
1548-
: ("arg" + std::to_string(i));
1549-
clang::QualType param_type = function
1550-
? function->getParamDecl(i)->getType()
1551-
: proto->getParamType(i);
1552-
bool is_parm_with_default_value =
1553-
function && function->getParamDecl(i)->hasDefaultArg();
1554-
1555-
if (is_parm_with_default_value) {
1560+
for (unsigned i = 0; i < num_params_to_bind; ++i) {
1561+
auto &pi = param_infos[i];
1562+
if (pi.has_default_value) {
15561563
StrCat("Some(");
15571564
}
15581565
if (!temp_refs[i].empty()) {
15591566
StrCat(temp_refs[i]);
1560-
} else if (clang::isa<clang::MaterializeTemporaryExpr>(arg)) {
1561-
convert_param_ty(param_type, arg);
1567+
} else if (clang::isa<clang::MaterializeTemporaryExpr>(pi.arg)) {
1568+
convert_param_ty(pi.type, pi.arg);
15621569
} else {
1563-
StrCat(std::format("_{}", param_name));
1570+
StrCat(std::format("_{}", pi.name));
15641571
}
1565-
if (is_parm_with_default_value) {
1572+
if (pi.has_default_value) {
15661573
StrCat(")");
15671574
}
15681575
StrCat(token::kComma);
@@ -3560,6 +3567,11 @@ std::string Converter::ConvertIRFragment(
35603567
} else if (auto *g = std::get_if<GenericFragment>(&frag)) {
35613568
result += Mapper::InstantiateTemplate(GetCalleeOrExpr(expr), g->name);
35623569
} else if (auto *ph = std::get_if<PlaceholderFragment>(&frag)) {
3570+
// Placeholder args are single-digit only ("a0".."a9"); enforced here
3571+
// to match the existing matchTemplate design constraint. A static_assert
3572+
// is not possible because ph->arg is runtime data from parsed rules.
3573+
assert(ph->arg.size() == 2 && std::isdigit(static_cast<unsigned char>(ph->arg[1])) &&
3574+
"placeholder arg must be a single-digit index");
35633575
auto arg_idx = static_cast<int>(ph->arg[1] - '0'); // "a0" -> 0
35643576
assert(arg_idx < static_cast<int>(all_args.size()));
35653577
auto *arg = all_args[arg_idx];

cpp2rust/converter/converter_lib.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -450,16 +450,13 @@ clang::Expr *ToAddrOf(clang::ASTContext &ctx, clang::Expr *expr) {
450450

451451
std::vector<clang::CXXRecordDecl *>
452452
GetNestedStructs(const clang::CXXRecordDecl *decl) {
453-
std::vector<clang::Decl *> nested_decls;
454-
auto predicate = [](auto *decl) {
455-
return clang::isa<clang::CXXRecordDecl>(decl) && !decl->isImplicit();
456-
};
457-
std::copy_if(decl->decls_begin(), decl->decls_end(),
458-
std::back_inserter(nested_decls), predicate);
459453
std::vector<clang::CXXRecordDecl *> nested_record_decls;
460-
auto op = [](auto *decl) { return clang::cast<clang::CXXRecordDecl>(decl); };
461-
std::transform(nested_decls.cbegin(), nested_decls.cend(),
462-
std::back_inserter(nested_record_decls), op);
454+
for (auto *d : decl->decls()) {
455+
if (auto *rec = clang::dyn_cast<clang::CXXRecordDecl>(d);
456+
rec && !rec->isImplicit()) {
457+
nested_record_decls.push_back(rec);
458+
}
459+
}
463460
return nested_record_decls;
464461
}
465462

cpp2rust/converter/mapper.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,10 @@ auto parallel_search(const Map &container, MatchPred &&match_func) {
333333
return std::make_pair(container.cend(), std::move(hit_match));
334334
}
335335

336-
// Serial fast-path: avoids thread-pool creation overhead for small maps.
337-
constexpr size_t kSerialThreshold = 16;
338-
if (container.size() <= kSerialThreshold) {
336+
// Parallel fast-path threshold: for small maps, skip thread-pool creation
337+
// and use a simple serial scan to avoid overhead.
338+
constexpr size_t kParallelThreshold = 16;
339+
if (container.size() <= kParallelThreshold) {
339340
for (auto it = container.cbegin(); it != container.cend(); ++it) {
340341
auto m = match_func(it->first);
341342
if (!m)

0 commit comments

Comments
 (0)