Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 10 additions & 34 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,6 @@ add_custom_target("check"
DEPENDS check-libcc2rs check-libcc2rs-macros check-unit
)

set(RULES_IR_DIR "${CMAKE_BINARY_DIR}/rules")

set(RUSTLS_HEADER "${PROJECT_SOURCE_DIR}/rules/rustls/rustls.h")
set(BROTLI_HEADERS
"${PROJECT_SOURCE_DIR}/rules/brotli/brotli/decode.h"
Expand Down Expand Up @@ -222,53 +220,33 @@ file(GLOB rule_subdirs CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/rules/*)
file(GLOB rule_common_headers CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/rules/common/*.h)
file(GLOB rule_indexer_sources CONFIGURE_DEPENDS
${PROJECT_SOURCE_DIR}/cpp2rust/rule_preprocessing/*
${PROJECT_SOURCE_DIR}/cpp2rust/converter/rules/rules_loader.*)
${PROJECT_SOURCE_DIR}/cpp2rust/converter/rules/rules_loader.*
${PROJECT_SOURCE_DIR}/cpp2rust/converter/rules/decls.*)
set(_common_headers)
foreach(_header IN LISTS rule_common_headers)
list(APPEND _common_headers --common-header=${_header})
endforeach()
set(cpp_rules_ir_outputs)
set(rules_index_parts)
set(rules_index_parts_dir ${CMAKE_BINARY_DIR}/rules_index/parts)
set(RULES_IR_DIR "${CMAKE_BINARY_DIR}/rules")
set(rust_rules_ir_outputs)
foreach(_rule_dir IN LISTS rule_subdirs)
file(GLOB _cpp_srcs ${_rule_dir}/src.c ${_rule_dir}/src.cpp ${_rule_dir}/src_cxx*.cpp)
if(NOT _cpp_srcs)
continue()
endif()
get_filename_component(_rule_name ${_rule_dir} NAME)
set(_out_dir ${RULES_IR_DIR}/${_rule_name})
set(_cpp_out ${_out_dir}/ir_src.json)
set(_cxxflags)
set(_cxxflags_file)
if(EXISTS ${_rule_dir}/cxxflags)
set(_cxxflags_file ${_rule_dir}/cxxflags)
file(STRINGS ${_cxxflags_file} _flags)
foreach(_flag IN LISTS _flags)
list(APPEND _cxxflags --cxxflags=${_flag})
endforeach()
endif()
set(_part ${rules_index_parts_dir}/${_rule_name}.json)
add_custom_command(
OUTPUT ${_cpp_out}
COMMAND ${CMAKE_COMMAND} -E make_directory ${_out_dir}
COMMAND $<TARGET_FILE:cpp-rule-preprocessor> --dir ${_rule_dir} --out ${_cpp_out} ${_cxxflags}
DEPENDS ${_cpp_srcs} ${_cxxflags_file} ${rule_common_headers} ${PROJECT_SOURCE_DIR}/cpp2rust/rule_preprocessing/cpp_rule_preprocessor.cpp ${RUSTLS_HEADER} ${BROTLI_HEADERS}
OUTPUT ${_part}
COMMAND ${CMAKE_COMMAND} -E make_directory ${rules_index_parts_dir}
COMMAND $<TARGET_FILE:cpp-rule-indexer> --dir ${_rule_dir} -o ${_part}
DEPENDS ${_cpp_srcs} ${rule_common_headers} ${rule_indexer_sources} ${RUSTLS_HEADER} ${BROTLI_HEADERS}
VERBATIM
)
list(APPEND cpp_rules_ir_outputs ${_cpp_out})

if(NOT _rule_name STREQUAL "builtin_types")
set(_part ${rules_index_parts_dir}/${_rule_name}.json)
add_custom_command(
OUTPUT ${_part}
COMMAND ${CMAKE_COMMAND} -E make_directory ${rules_index_parts_dir}
COMMAND $<TARGET_FILE:cpp-rule-indexer> --dir ${_rule_dir} -o ${_part}
DEPENDS ${_cpp_srcs} ${rule_common_headers} ${rule_indexer_sources} ${RUSTLS_HEADER} ${BROTLI_HEADERS}
VERBATIM
)
list(APPEND rules_index_parts ${_part})
endif()
list(APPEND rules_index_parts ${_part})

set(_out_dir ${RULES_IR_DIR}/${_rule_name})
set(_rust_srcs)
set(_rust_out)
if(EXISTS ${_rule_dir}/tgt_unsafe.rs)
Expand Down Expand Up @@ -297,8 +275,6 @@ foreach(_rule_dir IN LISTS rule_subdirs)
list(APPEND rust_rules_ir_outputs ${_rust_out})
endforeach()

add_custom_target("preprocess-cpp-rules" ALL DEPENDS ${cpp_rules_ir_outputs})

set(cpp_rules_index_outputs ${CMAKE_BINARY_DIR}/rules_index/c.json ${CMAKE_BINARY_DIR}/rules_index/cpp.json)
add_custom_command(
OUTPUT ${cpp_rules_index_outputs}
Expand Down
5 changes: 1 addition & 4 deletions cpp2rust/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ target_compile_definitions(cpp2rust_core PUBLIC "-DCLANG_RESOURCE_DIR=\"${LLVM_L
target_compile_definitions(cpp2rust_core PUBLIC "-DCOMPAT_INCLUDE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/compat\"")
target_compile_definitions(cpp2rust_core PUBLIC "-DRULES_SRC_DIR=\"${PROJECT_SOURCE_DIR}/rules\"")
target_compile_definitions(cpp2rust_core PUBLIC "-DRULES_INDEX_DIR=\"${CMAKE_BINARY_DIR}/rules_index\"")
target_compile_definitions(cpp2rust_core PUBLIC "-DRULES_IR_DIR=\"${CMAKE_BINARY_DIR}/rules\"")
target_compile_definitions(cpp2rust_core PUBLIC "-DRUST_STABLE_VERSION=\"${RUST_STABLE_VERSION}\"")

if (APPLE)
Expand All @@ -37,10 +38,6 @@ target_link_libraries(cpp2rust_core PUBLIC ${llvm_libs})
add_clang_executable(cpp2rust PARTIAL_SOURCES_INTENDED cpp2rust.cpp)
target_link_libraries(cpp2rust PRIVATE cpp2rust_core)

add_clang_executable(cpp-rule-preprocessor PARTIAL_SOURCES_INTENDED
rule_preprocessing/cpp_rule_preprocessor.cpp)
target_link_libraries(cpp-rule-preprocessor PRIVATE cpp2rust_core)

add_clang_executable(cpp-rule-indexer PARTIAL_SOURCES_INTENDED
rule_preprocessing/cpp_rule_indexer.cpp)
target_link_libraries(cpp-rule-indexer PRIVATE cpp2rust_core)
2 changes: 2 additions & 0 deletions cpp2rust/ast_consumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
#include <llvm/Support/ErrorHandling.h>

#include "converter/converter.h"
#include "converter/rules/registry.h"

namespace cpp2rust {
void ASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
if (CI_.getDiagnostics().hasErrorOccurred()) {
llvm::report_fatal_error(
"the translation unit and its loaded rules do not compile");
}
RuleRegistry::Load(CI_.getSema(), model_);
auto converter = CreateConverter(rs_code_, ctx, model_, rules_dir_);
converter->SetSema(CI_.getSema());
if (first_) {
Expand Down
54 changes: 31 additions & 23 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ bool Converter::Convert(clang::QualType qual_type) {
return TraverseType(qual_type);
}

std::string Converter::GetUnboxedTypeAsString(clang::QualType qual_type) {
return ToString(qual_type);
}

bool Converter::ConvertMappedType(clang::QualType qual_type) {
std::string type_as_string = Mapper::Map(*this, qual_type);
if (type_as_string == token::kIgnoreRule) {
Expand Down Expand Up @@ -182,7 +186,11 @@ bool Converter::VisitRecordType(clang::RecordType *type) {
}

StrCat(GetRecordName(decl));
RuleRegistry::AddRuleForUserDefinedType(ctx_, decl);
return false;
}

bool Converter::VisitEnumType(clang::EnumType *type) {
StrCat(GetRecordName(type->getDecl()));
return false;
}

Expand Down Expand Up @@ -738,11 +746,19 @@ bool Converter::IsPassThroughRule(clang::Expr *expr) const {
rule->body[0]);
}

bool Converter::RecordDerivesCopy(const clang::RecordDecl *decl) const {
auto *derives =
RuleRegistry::MappedDerives(ctx_, ctx_.getCanonicalTagType(decl));
return derives &&
std::find(derives->begin(), derives->end(), "Copy") != derives->end();
bool Converter::RecordDerivesCopy(const clang::RecordDecl *decl) {
if (auto rule =
RuleRegistry::Search(ctx_, ctx_.getCanonicalTagType(decl)).first) {
auto &derives = rule->type_info.derives;
return std::find(derives.begin(), derives.end(), "Copy") != derives.end();
}
decl = decl->getDefinition();
if (!decl) {
return false;
}
auto attrs = GetStructAttributes(decl);
return std::find(attrs.begin(), attrs.end(), std::string_view("Copy")) !=
attrs.end();
}

bool Converter::RecordHasCopyableFields(const clang::RecordDecl *decl) {
Expand Down Expand Up @@ -801,7 +817,6 @@ bool Converter::VisitRecordDecl(clang::RecordDecl *decl) {
return false;
}

RuleRegistry::AddRuleForUserDefinedType(ctx_, decl);
EmitRustStructOrUnion(decl);

return false;
Expand Down Expand Up @@ -868,9 +883,6 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
EmitReprC(decl);
}
auto attrs = GetStructAttributes(decl);
RuleRegistry::SetDerives(
ctx_, ctx_.getCanonicalTagType(decl),
std::vector<std::string>(attrs.begin(), attrs.end()));
StrCat("#[derive(");
for (auto *attr : attrs) {
StrCat(attr, ',');
Expand Down Expand Up @@ -968,9 +980,6 @@ void Converter::EmitReprC(clang::RecordDecl *decl) {
void Converter::EmitRustUnion(clang::RecordDecl *decl) {
EmitReprC(decl);
auto attrs = GetStructAttributes(decl);
RuleRegistry::SetDerives(
ctx_, ctx_.getCanonicalTagType(decl),
std::vector<std::string>(attrs.begin(), attrs.end()));
StrCat("#[derive(");
for (auto *attr : attrs) {
StrCat(attr, ',');
Expand All @@ -994,7 +1003,6 @@ void Converter::EmitRustUnion(clang::RecordDecl *decl) {
bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
decl->dump(log());

RuleRegistry::AddRuleForUserDefinedType(ctx_, decl);
if (!IsConvertibleCXXRecordDecl(decl)) {
return false;
}
Expand Down Expand Up @@ -1950,7 +1958,7 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) {
}

auto ty = GetReturnTypeOfFunction(expr);
auto ref = clang::dyn_cast<clang::ReferenceType>(ty);
auto ref = ty->getAs<clang::ReferenceType>();

if (ref && !isAddrOf() && !isVoid()) {
{
Expand Down Expand Up @@ -3220,6 +3228,10 @@ std::string Converter::ConvertDeclRef(clang::Expr *expr,

if (ShouldReplaceWithMappedBody(decl)) {
if (auto str = GetMappedAsString(expr); !str.empty()) {
if (RuleRegistry::ReturnsReference(expr) && !isAddrOf()) {
return std::format("({}{})", GetPointerDerefPrefix(expr->getType()),
str);
}
return str;
}
}
Expand Down Expand Up @@ -3979,7 +3991,6 @@ bool Converter::VisitEnumDecl(clang::EnumDecl *decl) {
if (Mapper::Contains(ctx_, ctx_.getCanonicalTagType(decl))) {
return false;
}
RuleRegistry::AddRuleForUserDefinedType(ctx_, decl);
auto name = GetRecordName(decl);
StrCat(std::format("pub type {} = {};", name,
GetUnsafeTypeAsString(decl->getIntegerType())));
Expand Down Expand Up @@ -5344,13 +5355,10 @@ std::string
Converter::ConvertInitFragment(clang::Expr *expr,
const std::vector<clang::Expr *> &all_args) {
const auto *tgt_ir = RuleRegistry::GetExprRule(ctx_, expr);
assert(tgt_ir && tgt_ir->init_type.valid());
auto *callee = clang::cast<clang::CallExpr>(expr)->getDirectCallee();
assert(callee);
auto type = GetSema()
.getTemplateInstantiationArgs(callee)(tgt_ir->init_type.depth,
tgt_ir->init_type.index)
.getAsType();
if (!tgt_ir || !tgt_ir->usesInit()) {
llvm::report_fatal_error("expression rule does not use Init");
}
auto type = RuleRegistry::GetInitType(expr);

Buffer buf(*this);
ConvertConstructFromArgs(
Expand Down
8 changes: 6 additions & 2 deletions cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

clang::ASTContext &GetASTContext() { return ctx_; }

virtual std::string GetUnboxedTypeAsString(clang::QualType qual_type);

bool VisitRecoveryExpr(clang::RecoveryExpr *expr);

virtual void EmitFilePreamble();
Expand All @@ -74,6 +76,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

virtual bool VisitRecordType(clang::RecordType *type);

bool VisitEnumType(clang::EnumType *type);

virtual bool VisitConstantArrayType(clang::ConstantArrayType *type);

virtual bool VisitIncompleteArrayType(clang::IncompleteArrayType *type);
Expand Down Expand Up @@ -363,7 +367,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
// Option<fn> implements Copy
virtual bool FunctionPointerImplementsCopy() const { return true; }

bool TypeIsCopyable(clang::QualType ty) const {
bool TypeIsCopyable(clang::QualType ty) {
if (ty->isFunctionPointerType() || ty->isFunctionType()) {
return FunctionPointerImplementsCopy();
}
Expand Down Expand Up @@ -785,7 +789,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

virtual bool TypeDerivesDefault(clang::QualType qual_type);

bool RecordDerivesCopy(const clang::RecordDecl *decl) const;
bool RecordDerivesCopy(const clang::RecordDecl *decl);

bool IsPassThroughRule(clang::Expr *expr) const;

Expand Down
18 changes: 3 additions & 15 deletions cpp2rust/converter/converter_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ bool IsAbstractUserClass(const clang::RecordDecl *decl) {
definition->isAbstract();
}

bool RefersToUserDefinedDecl(const clang::Expr *expr) {
bool ExprHasUserDefinedDecl(const clang::Expr *expr) {
expr = expr->IgnoreParenImpCasts();
const clang::Decl *decl = nullptr;
if (const auto *call = llvm::dyn_cast<clang::CallExpr>(expr)) {
Expand Down Expand Up @@ -1101,15 +1101,15 @@ const char *AccessSpecifierAsString(clang::AccessSpecifier spec) {
clang::QualType GetReturnTypeOfFunction(const clang::CallExpr *expr) {
if (auto *decl = expr->getCalleeDecl()) {
if (auto *fn = decl->getAsFunction()) {
return fn->getReturnType().getCanonicalType();
return fn->getReturnType();
}
}

auto callee_ty = expr->getCallee()->getType();
if (auto *ptr_ty = callee_ty->getAs<clang::PointerType>()) {
if (auto *fn_ty =
ptr_ty->getPointeeType()->getAs<clang::FunctionProtoType>()) {
return fn_ty->getReturnType().getCanonicalType();
return fn_ty->getReturnType();
}
}

Expand Down Expand Up @@ -1640,18 +1640,6 @@ clang::CXXConstructExpr *MakeConstructExpr(clang::ASTContext &ctx,
clang::SourceRange());
}

std::vector<clang::CXXRecordDecl *>
GetNestedStructs(const clang::CXXRecordDecl *decl) {
std::vector<clang::CXXRecordDecl *> nested_record_decls;
for (auto *d : decl->decls()) {
if (auto *rec = clang::dyn_cast<clang::CXXRecordDecl>(d);
rec && !rec->isImplicit()) {
nested_record_decls.push_back(rec);
}
}
return nested_record_decls;
}

std::optional<clang::ArrayRef<clang::TemplateArgument>>
GetTemplateArgs(clang::QualType qual_type, clang::Expr *expr) {
if (auto ty = clang::dyn_cast<clang::TemplateSpecializationType>(qual_type)) {
Expand Down
5 changes: 1 addition & 4 deletions cpp2rust/converter/converter_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ bool IsUserDefinedDecl(const clang::Decl *decl);

bool IsAbstractUserClass(const clang::RecordDecl *decl);

bool RefersToUserDefinedDecl(const clang::Expr *expr);
bool ExprHasUserDefinedDecl(const clang::Expr *expr);

bool IsUnsignedArithOp(const clang::BinaryOperator *expr);

Expand Down Expand Up @@ -274,9 +274,6 @@ clang::CXXConstructExpr *MakeConstructExpr(clang::ASTContext &ctx,
clang::CXXConstructorDecl *ctor,
llvm::ArrayRef<clang::Expr *> args);

std::vector<clang::CXXRecordDecl *>
GetNestedStructs(const clang::CXXRecordDecl *decl);

std::optional<clang::ArrayRef<clang::TemplateArgument>>
GetTemplateArgs(clang::QualType qual_type, clang::Expr *expr = nullptr);

Expand Down
2 changes: 0 additions & 2 deletions cpp2rust/converter/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@
#include "converter/factory.h"

#include "converter/models/converter_refcount.h"
#include "converter/rules/registry.h"

namespace cpp2rust {

std::unique_ptr<Converter> CreateConverter(std::string &rs_code,
clang::ASTContext &ctx, Model model,
const std::string &rules_dir) {
RuleRegistry::Load(model, rules_dir);
switch (model) {
case Model::kUnsafe:
return std::make_unique<Converter>(rs_code, ctx);
Expand Down
Loading
Loading