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
63 changes: 62 additions & 1 deletion cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "converter/models/converter_refcount.h"

#include <clang/AST/RecordLayout.h>
#include <clang/Basic/OperatorKinds.h>

#include <format>
Expand Down Expand Up @@ -497,10 +498,70 @@ void ConverterRefCount::AddDropTrait(const clang::CXXRecordDecl *decl) {
StrCat("}");
}

static bool recordImplementsByteRepr(const clang::RecordDecl *decl) {
if (decl->isUnion()) {
return false;
}

// ByteRepr is only supported for user-defined structs that contain ByteRepr
// fields.
for (auto *f : decl->fields()) {
auto qt = f->getType();
if (qt->isEnumeralType()) {
return false;
}
if (!qt->isIntegerType() && !qt->isFloatingType()) {
return false;
}
}

return true;
}

void ConverterRefCount::AddByteReprTrait(const clang::RecordDecl *decl) {
auto struct_name = GetRecordName(decl);

if (!recordImplementsByteRepr(decl)) {
StrCat(std::format("impl ByteRepr for {}", struct_name));
PushBrace brace(*this);
return;
}

StrCat(std::format("impl ByteRepr for {}", struct_name));
PushBrace brace(*this);
PushBrace impl_brace(*this);

const auto &layout = ctx_.getASTRecordLayout(decl);

StrCat("fn to_bytes(&self, buf: &mut [u8])");
{
PushBrace fn_brace(*this);
unsigned idx = 0;
for (auto *field : decl->fields()) {
auto byte_off = layout.getFieldOffset(idx) / 8;
auto byte_size = ctx_.getTypeSize(field->getType()) / 8;
StrCat(std::format("(*self.{}.borrow()).to_bytes(&mut buf[{}..{}]);",
GetNamedDeclAsString(field), byte_off,
byte_off + byte_size));
++idx;
}
}

StrCat("fn from_bytes(buf: &[u8]) -> Self");
{
PushBrace fn_brace(*this);
StrCat("Self");
PushBrace lit_brace(*this);
unsigned idx = 0;
for (auto *field : decl->fields()) {
auto byte_off = layout.getFieldOffset(idx) / 8;
auto byte_size = ctx_.getTypeSize(field->getType()) / 8;
StrCat(std::format(
"{}: Rc::new(RefCell::new(<{}>::from_bytes(&buf[{}..{}]))),",
GetNamedDeclAsString(field), Mapper::Map(field->getType()), byte_off,
byte_off + byte_size));
++idx;
}
}
}

std::string
Expand Down
26 changes: 26 additions & 0 deletions tests/unit/memcpy_struct_struct.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

struct Entry {
uint8_t bits;
uint16_t value;
};

int main(void) {
struct Entry table[8] = {
{1, 0x1111}, {2, 0x2222}, {3, 0x3333}, {4, 0x4444},
{0, 0}, {0, 0}, {0, 0}, {0, 0},
};
size_t table_size = 4;

memcpy(&table[table_size], &table[0], table_size * sizeof(table[0]));

assert(table[4].bits == 1 && table[4].value == 0x1111);
assert(table[5].bits == 2 && table[5].value == 0x2222);
assert(table[6].bits == 3 && table[6].value == 0x3333);
assert(table[7].bits == 4 && table[7].value == 0x4444);

return 0;
}
11 changes: 10 additions & 1 deletion tests/unit/out/refcount/addr_of_global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,16 @@ impl Clone for Inner {
this
}
}
impl ByteRepr for Inner {}
impl ByteRepr for Inner {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.value.borrow()).to_bytes(&mut buf[0..4]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
value: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
}
}
}
#[derive(Default)]
pub struct Outer {
pub p: Value<Ptr<Inner>>,
Expand Down
87 changes: 80 additions & 7 deletions tests/unit/out/refcount/anonymous-struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,18 @@ impl Clone for Outer_Named {
this
}
}
impl ByteRepr for Outer_Named {}
impl ByteRepr for Outer_Named {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.a.borrow()).to_bytes(&mut buf[0..4]);
(*self.b.borrow()).to_bytes(&mut buf[4..8]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
a: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
b: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_0 {
pub c: Value<i32>,
Expand All @@ -35,7 +46,18 @@ impl Clone for Outer_anon_0 {
this
}
}
impl ByteRepr for Outer_anon_0 {}
impl ByteRepr for Outer_anon_0 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.c.borrow()).to_bytes(&mut buf[0..4]);
(*self.d.borrow()).to_bytes(&mut buf[4..8]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
c: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
d: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_1 {
pub g: Value<i32>,
Expand All @@ -50,7 +72,18 @@ impl Clone for Outer_anon_1 {
this
}
}
impl ByteRepr for Outer_anon_1 {}
impl ByteRepr for Outer_anon_1 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.g.borrow()).to_bytes(&mut buf[0..4]);
(*self.h.borrow()).to_bytes(&mut buf[4..8]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
g: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
h: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_2 {
pub e: Value<i32>,
Expand All @@ -65,7 +98,18 @@ impl Clone for Outer_anon_2 {
this
}
}
impl ByteRepr for Outer_anon_2 {}
impl ByteRepr for Outer_anon_2 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.e.borrow()).to_bytes(&mut buf[0..4]);
(*self.f.borrow()).to_bytes(&mut buf[4..8]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
e: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
f: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_3_anon_0 {
pub j: Value<i32>,
Expand All @@ -78,7 +122,16 @@ impl Clone for Outer_anon_3_anon_0 {
this
}
}
impl ByteRepr for Outer_anon_3_anon_0 {}
impl ByteRepr for Outer_anon_3_anon_0 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.j.borrow()).to_bytes(&mut buf[0..4]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
j: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_3_anon_1 {
pub k: Value<i32>,
Expand All @@ -91,7 +144,16 @@ impl Clone for Outer_anon_3_anon_1 {
this
}
}
impl ByteRepr for Outer_anon_3_anon_1 {}
impl ByteRepr for Outer_anon_3_anon_1 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.k.borrow()).to_bytes(&mut buf[0..4]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
k: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_3 {
pub i: Value<i32>,
Expand Down Expand Up @@ -211,7 +273,18 @@ fn main_0() -> i32 {
this
}
}
impl ByteRepr for anon_0 {};
impl ByteRepr for anon_0 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.x.borrow()).to_bytes(&mut buf[0..4]);
(*self.z.borrow()).to_bytes(&mut buf[4..8]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
x: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
z: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
}
}
};
let s: Value<anon_0> = Rc::new(RefCell::new(<anon_0>::default()));
(*(*s.borrow()).x.borrow_mut()) = 1;
(*(*s.borrow()).z.borrow_mut()) = 2;
Expand Down
87 changes: 80 additions & 7 deletions tests/unit/out/refcount/anonymous-struct_c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,97 @@ pub struct Named {
pub a: Value<i32>,
pub b: Value<i32>,
}
impl ByteRepr for Named {}
impl ByteRepr for Named {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.a.borrow()).to_bytes(&mut buf[0..4]);
(*self.b.borrow()).to_bytes(&mut buf[4..8]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
a: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
b: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_0 {
pub c: Value<i32>,
pub d: Value<i32>,
}
impl ByteRepr for Outer_anon_0 {}
impl ByteRepr for Outer_anon_0 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.c.borrow()).to_bytes(&mut buf[0..4]);
(*self.d.borrow()).to_bytes(&mut buf[4..8]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
c: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
d: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_1 {
pub g: Value<i32>,
pub h: Value<i32>,
}
impl ByteRepr for Outer_anon_1 {}
impl ByteRepr for Outer_anon_1 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.g.borrow()).to_bytes(&mut buf[0..4]);
(*self.h.borrow()).to_bytes(&mut buf[4..8]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
g: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
h: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_2 {
pub e: Value<i32>,
pub f: Value<i32>,
}
impl ByteRepr for Outer_anon_2 {}
impl ByteRepr for Outer_anon_2 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.e.borrow()).to_bytes(&mut buf[0..4]);
(*self.f.borrow()).to_bytes(&mut buf[4..8]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
e: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
f: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_3_anon_0 {
pub j: Value<i32>,
}
impl ByteRepr for Outer_anon_3_anon_0 {}
impl ByteRepr for Outer_anon_3_anon_0 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.j.borrow()).to_bytes(&mut buf[0..4]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
j: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_3_anon_1 {
pub k: Value<i32>,
}
impl ByteRepr for Outer_anon_3_anon_1 {}
impl ByteRepr for Outer_anon_3_anon_1 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.k.borrow()).to_bytes(&mut buf[0..4]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
k: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
}
}
}
#[derive(Default)]
pub struct Outer_anon_3 {
pub i: Value<i32>,
Expand Down Expand Up @@ -113,7 +175,18 @@ fn main_0() -> i32 {
pub x: Value<i32>,
pub z: Value<i32>,
}
impl ByteRepr for anon_0 {};
impl ByteRepr for anon_0 {
fn to_bytes(&self, buf: &mut [u8]) {
(*self.x.borrow()).to_bytes(&mut buf[0..4]);
(*self.z.borrow()).to_bytes(&mut buf[4..8]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
x: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
z: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
}
}
};
let s: Value<anon_0> = <Value<anon_0>>::default();
(*(*s.borrow()).x.borrow_mut()) = 1;
(*(*s.borrow()).z.borrow_mut()) = 2;
Expand Down
Loading
Loading