Skip to content
  •  
  •  
  •  
46 changes: 34 additions & 12 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ namespace cpp2rust {
std::unordered_map<std::string, std::string> Converter::inner_structs_;
std::unordered_set<std::string> Converter::decl_ids_;
std::unordered_set<std::string> Converter::globals_;
std::vector<std::string> Converter::global_inits_;
std::unordered_set<std::string> Converter::abstract_structs_;
Converter::RecordIndex Converter::record_decls_;
std::map<std::string, Converter::MethodsOnPtr> Converter::methods_on_ptr_;
Expand Down Expand Up @@ -59,8 +60,7 @@ use std::rc::Rc;
)");
}

std::string Converter::EmitMethodsOnPtr() {
std::string out;
void Converter::EmitMethodsOnPtr(std::string &out) {
for (const auto &[name, methods] : methods_on_ptr_) {
out += methods.trait_header;
out += " {\n";
Expand All @@ -71,18 +71,30 @@ std::string Converter::EmitMethodsOnPtr() {
out += methods.impl_body;
out += "}\n";
}
return out;
}

std::string Converter::EmitOpaqueRecords() {
std::string out;
std::string Converter::ForceGlobalInit(const clang::VarDecl *decl) {
return std::format("std::cell::LazyCell::force(&*&raw const {});",
GetNamedDeclAsString(decl));
}

void Converter::EmitGlobalInits(Model model, std::string &out) {
out += model == Model::kUnsafe ? "pub unsafe fn __cpp2rust_init_globals() {\n"
: "pub fn __cpp2rust_init_globals() {\n";
for (const auto &line : global_inits_) {
out += line;
out += '\n';
}
out += "}\n";
}

void Converter::EmitOpaqueRecords(std::string &out) {
record_decls_.ForEachUndefined([&](const std::string &name) {
out += "#[derive(Clone, Copy, Default, ByteRepr)]";
out += "pub struct ";
out += name;
out += ";\n";
});
return out;
}

bool Converter::VisitRecoveryExpr(clang::RecoveryExpr *expr) {
Expand Down Expand Up @@ -515,6 +527,7 @@ bool Converter::ConvertVarDeclSkipInit(clang::VarDecl *decl) {
StrCat(AccessSpecifierAsString(decl->getAccess()), keyword::kStatic,
keyword_mut_);
ENSURE(decl_ids_.insert(GetID(decl)).second);
global_inits_.push_back(ForceGlobalInit(decl));
} else if (decl->isStaticLocal()) {
StrCat(keyword::kStatic, keyword_mut_);
} else if (decl->isLocalVarDecl()) {
Expand All @@ -535,7 +548,10 @@ bool Converter::ConvertVarDeclSkipInit(clang::VarDecl *decl) {
if (is_parm_with_default_value) {
StrCat("Option<");
}
Convert(qual_type);
{
PushLazyType lazy(*this, IsGlobalVar(decl) && LazyStaticInit());
Convert(qual_type);
}
if (is_parm_with_default_value) {
StrCat('>');
}
Expand Down Expand Up @@ -600,8 +616,9 @@ void Converter::ConvertGlobalVarDecl(clang::VarDecl *decl) {
PushConstInitializer static_init(*this, decl->isFileVarDecl() ||
decl->isStaticLocal());
StrCat(token::kAssign);
StrCat(keyword_unsafe_);
{
PushLazyInit lazy(*this, LazyStaticInit());
StrCat(keyword_unsafe_);
PushBrace push(*this);
ConvertVarDeclInitializer(decl);
}
Expand Down Expand Up @@ -2925,7 +2942,11 @@ std::string Converter::ConvertDeclRefExpr(clang::DeclRefExpr *expr) {
}

if (IsGlobalVar(expr)) {
return GetNamedDeclAsString(expr->getDecl());
if (LazyStaticInit()) {
return std::format("(*std::cell::LazyCell::force_mut(&mut *&raw mut {}))",
GetNamedDeclAsString(decl));
}
return GetNamedDeclAsString(decl);
}

return GetNamedDeclAsString(decl);
Expand Down Expand Up @@ -4279,14 +4300,15 @@ pub fn main() {{
let mut argv: Vec<*mut libc::c_char> = args.iter().map(|arg| arg.as_ptr() as *mut libc::c_char).collect();
argv.push(::std::ptr::null_mut());
unsafe {{
__cpp2rust_init_globals();
::std::process::exit(main_0((argv.len() - 1) as i32, argv.as_mut_ptr()) as i32)
}}
}})",
main_function_name));
} else {
StrCat(std::format(
"pub fn main() {{ unsafe {{ std::process::exit({}() as i32); }} }}",
main_function_name));
StrCat(std::format("pub fn main() {{ unsafe {{ __cpp2rust_init_globals(); "
"std::process::exit({}() as i32); }} }}",
main_function_name));
}
}

Expand Down
29 changes: 18 additions & 11 deletions cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <vector>

#include "converter/converter_lib.h"
#include "converter/factory.h"
#include "converter/lex.h"
#include "converter/translation_rule.h"
#include "logging.h"
Expand Down Expand Up @@ -51,9 +52,10 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

virtual void EmitFilePreamble();

static std::string EmitOpaqueRecords();
static void EmitOpaqueRecords(std::string &out);
static void EmitGlobalInits(Model model, std::string &out);

static std::string EmitMethodsOnPtr();
static void EmitMethodsOnPtr(std::string &out);

virtual bool VisitBuiltinType(clang::BuiltinType *type);

Expand Down Expand Up @@ -98,6 +100,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
virtual bool VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *decl);

virtual bool VisitVarDecl(clang::VarDecl *decl);
virtual bool LazyStaticInit() const { return true; }
virtual std::string ForceGlobalInit(const clang::VarDecl *decl);

void ConvertVarDecl(clang::VarDecl *decl);

Expand Down Expand Up @@ -454,18 +458,18 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
#define StrCat(...) _StrCat(__FUNCTION__, __LINE__, __VA_ARGS__)

inline bool is_empty(char c) { return false; }
inline bool is_empty(const char* s) { return s == nullptr || *s == '\0'; }
template <size_t N>
inline bool is_empty(const char (&s)[N]) { return s[0] == '\0'; }
template <typename T>
inline bool is_empty(const T &s) { return s.empty(); }
inline bool is_empty(const char *s) { return s == nullptr || *s == '\0'; }
template <size_t N> inline bool is_empty(const char (&s)[N]) {
return s[0] == '\0';
}
template <typename T> inline bool is_empty(const T &s) { return s.empty(); }

template <typename... Ts>
inline void _StrCat(const char *func, int line, const Ts &...vals) {
log() << '[' << func << ':' << line << "] ";
((log() << vals << '\n',
*rs_code_ += vals,
(is_empty(vals) ? void() : void(*rs_code_ += ' '))), ...);
((log() << vals << '\n', *rs_code_ += vals,
(is_empty(vals) ? void() : void(*rs_code_ += ' '))),
...);
}

class Buffer {
Expand All @@ -481,7 +485,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
std::string str() && { return std::move(partial_code); }
};

template <char kOpen, char kClose> class PushDelim {
template <auto kOpen, auto kClose> class PushDelim {
Converter &c;
bool enabled;

Expand All @@ -506,6 +510,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
PushDelim<token::kOpenCurlyBracket, token::kCloseCurlyBracket>;
using PushParen = PushDelim<token::kOpenParen, token::kCloseParen>;
using PushBracket = PushDelim<token::kOpenBracket, token::kCloseBracket>;
using PushLazyType = PushDelim<token::kLazyCellType, token::kGt>;
using PushLazyInit = PushDelim<token::kLazyCellNew, token::kCloseParen>;

template <typename T>
inline std::string
Expand Down Expand Up @@ -1038,6 +1044,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
std::vector<ExprKind> curr_expr_kind_;
static std::unordered_map<std::string, std::string> inner_structs_;
static std::unordered_set<std::string> globals_;
static std::vector<std::string> global_inits_;
clang::Sema *sema_ = nullptr;
};
} // namespace cpp2rust
2 changes: 2 additions & 0 deletions cpp2rust/converter/lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ inline constexpr char kDiv = '/';
inline constexpr char kLt = '<';
inline constexpr char kGt = '>';
inline constexpr char kNewLine = '\n';
inline constexpr const char kLazyCellType[] = "std::cell::LazyCell<";
inline constexpr const char kLazyCellNew[] = "std::cell::LazyCell::new(||";
} // namespace token

namespace keyword {
Expand Down
8 changes: 7 additions & 1 deletion cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2448,6 +2448,10 @@ void ConverterRefCount::ConvertPointerSubscript(
}
}

std::string ConverterRefCount::ForceGlobalInit(const clang::VarDecl *decl) {
return std::format("let _ = {}.with(|_| ());", GetNamedDeclAsString(decl));
}

void ConverterRefCount::ConvertFunctionMain(
const clang::FunctionDecl *decl,
const std::string_view main_function_name) {
Expand All @@ -2461,12 +2465,14 @@ pub fn main() {{
argv.iter().map(|x| {{ x.borrow_mut().push(0); x.as_pointer() }}).collect(),
));
(*argv.borrow_mut()).push(Ptr::null());
__cpp2rust_init_globals();
::std::process::exit({}(::std::env::args().len() as i32,
argv.as_pointer()));
}})",
main_function_name));
} else {
StrCat(std::format("pub fn main() {{ std::process::exit({}()); }}",
StrCat(std::format("pub fn main() {{ __cpp2rust_init_globals(); "
"std::process::exit({}()); }}",
main_function_name));
}
}
Expand Down
2 changes: 2 additions & 0 deletions cpp2rust/converter/models/converter_refcount.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ class ConverterRefCount final : public Converter {
void EmitFunctionPreamble(clang::FunctionDecl *decl) override;

bool VisitVarDecl(clang::VarDecl *decl) override;
bool LazyStaticInit() const override { return false; }
std::string ForceGlobalInit(const clang::VarDecl *decl) override;

void ConvertGlobalVarDecl(clang::VarDecl *decl) override;

Expand Down
10 changes: 6 additions & 4 deletions cpp2rust/cpp2rust_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ std::string TranspileSrc(std::string_view cc_code, Model model,
rules_dir),
cc_code, tool_args, std::filesystem::path(filename).filename().string(),
filename.ends_with(".c") ? CLANG_C_COMPILER : CLANG_CXX_COMPILER);
rs_code += Converter::EmitOpaqueRecords();
rs_code += Converter::EmitMethodsOnPtr();
Converter::EmitOpaqueRecords(rs_code);
Converter::EmitMethodsOnPtr(rs_code);
Converter::EmitGlobalInits(model, rs_code);
return rs_code;
}

Expand Down Expand Up @@ -71,8 +72,9 @@ std::string TranspileDir(std::string_view build_dir, Model model,
std::string rs_code;
FrontendActionFactory factory(rs_code, model, rules_dir);
Tool.run(&factory);
rs_code += Converter::EmitOpaqueRecords();
rs_code += Converter::EmitMethodsOnPtr();
Converter::EmitOpaqueRecords(rs_code);
Converter::EmitMethodsOnPtr(rs_code);
Converter::EmitGlobalInits(model, rs_code);
return rs_code;
}
} // namespace cpp2rust
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub fn a_value_1() -> i32 {
return (*x.borrow());
}
pub fn main() {
__cpp2rust_init_globals();
std::process::exit(main_0());
}
fn main_0() -> i32 {
Expand All @@ -28,3 +29,4 @@ pub fn b_value_2() -> i32 {
(*x.borrow_mut()) |= (anon_3_BETA as i32);
return (*x.borrow());
}
pub fn __cpp2rust_init_globals() {}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub unsafe fn a_value_1() -> i32 {
}
pub fn main() {
unsafe {
__cpp2rust_init_globals();
std::process::exit(main_0() as i32);
}
}
Expand All @@ -30,3 +31,4 @@ pub unsafe fn b_value_2() -> i32 {
x |= (anon_3_BETA as i32);
return x;
}
pub unsafe fn __cpp2rust_init_globals() {}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub fn a_value_0() -> i32 {
return (*(*w.borrow()).id.borrow());
}
pub fn main() {
__cpp2rust_init_globals();
std::process::exit(main_0());
}
fn main_0() -> i32 {
Expand All @@ -51,3 +52,4 @@ pub fn b_value_1() -> i32 {
let w: Value<widget_enum> = Rc::new(RefCell::new(widget_enum_WIDGET_C));
return ((*w.borrow()) as i32);
}
pub fn __cpp2rust_init_globals() {}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub unsafe fn a_value_0() -> i32 {
}
pub fn main() {
unsafe {
__cpp2rust_init_globals();
std::process::exit(main_0() as i32);
}
}
Expand All @@ -34,3 +35,4 @@ pub unsafe fn b_value_1() -> i32 {
let mut w: widget_enum = widget_enum_WIDGET_C;
return (w as i32);
}
pub unsafe fn __cpp2rust_init_globals() {}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub fn sum_0(s: Ptr<S>) -> i32 {
};
}
pub fn main() {
__cpp2rust_init_globals();
std::process::exit(main_0());
}
fn main_0() -> i32 {
Expand Down Expand Up @@ -110,3 +111,4 @@ impl SImpl for Ptr<S> {
return (*self).clone();
}
}
pub fn __cpp2rust_init_globals() {}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub unsafe fn sum_0(s: *const S) -> i32 {
}
pub fn main() {
unsafe {
__cpp2rust_init_globals();
std::process::exit(main_0() as i32);
}
}
Expand All @@ -73,3 +74,4 @@ pub unsafe fn shuffle_1(mut x: i32) -> i32 {
assert!(b.v.is_empty());
return (unsafe { sum_0(&c) });
}
pub unsafe fn __cpp2rust_init_globals() {}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::io::{Read, Seek, Write};
use std::os::fd::AsFd;
use std::rc::{Rc, Weak};
pub fn main() {
__cpp2rust_init_globals();
std::process::exit(main_0());
}
fn main_0() -> i32 {
Expand All @@ -29,3 +30,4 @@ pub fn helper_0(x: i32) -> i32 {
&({ unrelated3_3() });
return ((*x.borrow()) + 1);
}
pub fn __cpp2rust_init_globals() {}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
use std::rc::Rc;
pub fn main() {
unsafe {
__cpp2rust_init_globals();
std::process::exit(main_0() as i32);
}
}
Expand All @@ -30,3 +31,4 @@ pub unsafe fn helper_0(mut x: i32) -> i32 {
&(unsafe { unrelated3_3() });
return ((x) + (1));
}
pub unsafe fn __cpp2rust_init_globals() {}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::io::{Read, Seek, Write};
use std::os::fd::AsFd;
use std::rc::{Rc, Weak};
pub fn main() {
__cpp2rust_init_globals();
std::process::exit(main_0());
}
fn main_0() -> i32 {
Expand All @@ -29,3 +30,4 @@ pub fn helper_0(x: i32) -> i32 {
&({ unrelated3_3() });
return ((*x.borrow()) + 1);
}
pub fn __cpp2rust_init_globals() {}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
use std::rc::Rc;
pub fn main() {
unsafe {
__cpp2rust_init_globals();
std::process::exit(main_0() as i32);
}
}
Expand All @@ -30,3 +31,4 @@ pub unsafe fn helper_0(mut x: i32) -> i32 {
&(unsafe { unrelated3_3() });
return ((x) + (1));
}
pub unsafe fn __cpp2rust_init_globals() {}
Loading
Loading