From e4bae85c9a0233921084b68d34d4e8473117cefb Mon Sep 17 00:00:00 2001 From: Anders Elfgren Date: Mon, 4 Mar 2024 14:01:13 +0100 Subject: [PATCH 1/7] Added better support for bitfields. --- src/Transpiler.zig | 147 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 121 insertions(+), 26 deletions(-) diff --git a/src/Transpiler.zig b/src/Transpiler.zig index 2c97a2d..83c6e2a 100644 --- a/src/Transpiler.zig +++ b/src/Transpiler.zig @@ -96,6 +96,57 @@ const PrimitivesTypeLUT = std.ComptimeStringMap([]const u8, .{ .{ "std::string", "cpp.String" }, }); +const TypeToByteSizeLUT = std.ComptimeStringMap(u32, .{ + .{ "bool", @sizeOf(bool) }, + .{ "c_int", @sizeOf(c_int) }, + .{ "c_long", @sizeOf(c_long) }, + .{ "c_longdouble", @sizeOf(c_longdouble) }, + .{ "c_longlong", @sizeOf(c_longlong) }, + .{ "c_short", @sizeOf(c_short) }, + .{ "c_uint", @sizeOf(c_uint) }, + .{ "c_ulong", @sizeOf(c_ulong) }, + .{ "c_ulonglong", @sizeOf(c_ulonglong) }, + .{ "c_ushort", @sizeOf(c_ushort) }, + .{ "f32", @sizeOf(f32) }, + .{ "f64", @sizeOf(f64) }, + .{ "i128", @sizeOf(i128) }, + .{ "i16", @sizeOf(i16) }, + .{ "i32", @sizeOf(i32) }, + .{ "i64", @sizeOf(i64) }, + .{ "i8", @sizeOf(i8) }, + .{ "isize", @sizeOf(isize) }, + .{ "u128", @sizeOf(u128) }, + .{ "u16", @sizeOf(u16) }, + .{ "u32", @sizeOf(u32) }, + .{ "u64", @sizeOf(u64) }, + .{ "u8", @sizeOf(u8) }, + .{ "usize", @sizeOf(usize) }, +}); + +const TypeToSignedLUT = std.ComptimeStringMap(bool, .{ + .{ "c_int", true }, + .{ "c_long", true }, + .{ "c_longdouble", true }, + .{ "c_longlong", true }, + .{ "c_short", true }, + .{ "c_uint", false }, + .{ "c_ulong", false }, + .{ "c_ulonglong", false }, + .{ "c_ushort", false }, + .{ "i128", true }, + .{ "i16", true }, + .{ "i32", true }, + .{ "i64", true }, + .{ "i8", true }, + .{ "isize", true }, + .{ "u128", false }, + .{ "u16", false }, + .{ "u32", false }, + .{ "u64", false }, + .{ "u8", false }, + .{ "usize", false }, +}); + const ScopeTag = enum { root, class, @@ -599,8 +650,10 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { try self.namespace.full_path.appendSlice(name); var is_in_bitfield = false; + var bitfield_type_bytes_curr: ?u32 = null; + var bitfield_signed_curr = false; var bitfield_group: u32 = 0; - var bitfield_struct_size_remaining: u32 = 0; + var bitfield_struct_bits_remaining: u32 = 0; for (inner.?.array.items) |*item| { if (item.object.getPtr("isImplicit")) |implicit| { @@ -625,39 +678,72 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { } } + const item_inner = item.object.getPtr("inner"); + const item_type = try self.transpileType(typeQualifier(item).?); + defer self.allocator.free(item_type); + + try self.writeDocs(item_inner); + + var bitfield_field_bits: u32 = 0; + is_in_bitfield = false; + if (item.object.getPtr("isBitfield")) |is_bitfield| { - if (!is_in_bitfield and is_bitfield.bool) { - is_in_bitfield = true; - bitfield_group += 1; + if (!is_bitfield.bool) { + // Not sure when this would be true. + std.debug.assert(false); + } + + is_in_bitfield = true; - // TODO: Calculate this. - bitfield_struct_size_remaining = 32; + const inner_value_index = 0; // Not sure if this is always 0. + const inner_value_elem = item_inner.?.array.items[inner_value_index]; + const bitfield_field_bits_str = inner_value_elem.object.getPtr("value").?.string; + bitfield_field_bits = try std.fmt.parseInt(u32, bitfield_field_bits_str, 10); - try self.out.print(" field_{d}: packed struct(u{d}) {{\n", .{ bitfield_group, bitfield_struct_size_remaining }); - } else if (is_in_bitfield and is_bitfield.bool) { - // pass - } else if (is_in_bitfield) { - is_in_bitfield = false; - try self.finalizeBitfield(bitfield_struct_size_remaining); + const bitfield_type_bytes = TypeToByteSizeLUT.get(item_type).?; + const bitfield_type_bits = bitfield_type_bytes * 8; + const bitfield_signed = TypeToSignedLUT.get(item_type).?; + + const bitfield_type_changed = bitfield_type_bytes_curr == null or bitfield_type_bytes_curr.? != bitfield_type_bytes; + const bitfield_sign_changed = bitfield_signed_curr != bitfield_signed; + if (bitfield_type_changed or bitfield_sign_changed) { + // A new bitfield + // - or - + // Underlying type's size changed, need to start a new bitfield + + // NOTE: C's behavior of padding when the type and signedness has changed seems tricky and perhaps + // not even consistent across platforms/compilers so leaving a warning when it's noticed. + + if (bitfield_type_bytes_curr != null) { + if (bitfield_struct_bits_remaining > 0) { + try self.out.print(" /// C2Z WARNING: This perhaps shouldn't be padded in this way! \n", .{}); + } + + try self.finalizeBitfield(bitfield_struct_bits_remaining); + } + + bitfield_type_bytes_curr = bitfield_type_bytes; + bitfield_signed_curr = bitfield_signed; + + bitfield_group += 1; + try self.startBitfield(bitfield_group, bitfield_type_bits); + bitfield_struct_bits_remaining = bitfield_type_bits; + } else if (is_in_bitfield and bitfield_struct_bits_remaining < bitfield_field_bits) { + // Existing bitfield but new field doesn't fit + try self.finalizeBitfield(bitfield_struct_bits_remaining); + + bitfield_group += 1; + try self.startBitfield(bitfield_group, bitfield_type_bits); + bitfield_struct_bits_remaining = bitfield_type_bits; } - } else if (is_in_bitfield) { + } else { is_in_bitfield = false; - try self.finalizeBitfield(bitfield_struct_size_remaining); } - const item_inner = item.object.getPtr("inner"); - try self.writeDocs(item_inner); - const field_type = switch (is_in_bitfield) { true => blk: { - const inner_value_index = 0; // Not sure if this is always 0. - const inner_value_elem = item_inner.?.array.items[inner_value_index]; - const bitfield_size_str = inner_value_elem.object.getPtr("value").?.string; - const bitfield_size = try std.fmt.parseInt(u32, bitfield_size_str, 10); - // TODO: Handle this. - std.debug.assert(bitfield_struct_size_remaining >= bitfield_size); - bitfield_struct_size_remaining -= bitfield_size; - break :blk try fmt.allocPrint(self.allocator, "u{d}", .{bitfield_size}); + bitfield_struct_bits_remaining -= bitfield_field_bits; + break :blk try self.addBitfieldField(bitfield_signed_curr, bitfield_field_bits); }, false => try self.transpileType(typeQualifier(item).?), }; @@ -742,7 +828,7 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { if (is_in_bitfield) { is_in_bitfield = false; - try self.finalizeBitfield(bitfield_struct_size_remaining); + try self.finalizeBitfield(bitfield_struct_bits_remaining); } // declarations must be after fields @@ -759,6 +845,15 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { } } +fn startBitfield(self: *Self, bitfield_group: u32, bitfield_type_bits: u32) !void { + try self.out.print(" bitfield_{d}: packed struct(u{d}) {{\n", .{ bitfield_group, bitfield_type_bits }); +} + +fn addBitfieldField(self: *Self, is_signed: bool, bitfield_field_bits: u32) ![]u8 { + const signed_str = if (is_signed) "i" else "u"; + return try fmt.allocPrint(self.allocator, "{s}{d}", .{ signed_str, bitfield_field_bits }); +} + fn finalizeBitfield(self: *Self, bits_remaining: u32) !void { if (bits_remaining > 0) { try self.out.print(" /// Padding added by c2z\n", .{}); From 1751b93eae0215ba03f4188e64cd42c377f1f39f Mon Sep 17 00:00:00 2001 From: Anders Elfgren Date: Mon, 4 Mar 2024 16:39:38 +0100 Subject: [PATCH 2/7] Fixed some issues with bitfields. --- src/Transpiler.zig | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/Transpiler.zig b/src/Transpiler.zig index 83c6e2a..2b78c8a 100644 --- a/src/Transpiler.zig +++ b/src/Transpiler.zig @@ -124,6 +124,7 @@ const TypeToByteSizeLUT = std.ComptimeStringMap(u32, .{ }); const TypeToSignedLUT = std.ComptimeStringMap(bool, .{ + .{ "bool", false }, .{ "c_int", true }, .{ "c_long", true }, .{ "c_longdouble", true }, @@ -649,7 +650,6 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { } try self.namespace.full_path.appendSlice(name); - var is_in_bitfield = false; var bitfield_type_bytes_curr: ?u32 = null; var bitfield_signed_curr = false; var bitfield_group: u32 = 0; @@ -685,7 +685,6 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { try self.writeDocs(item_inner); var bitfield_field_bits: u32 = 0; - is_in_bitfield = false; if (item.object.getPtr("isBitfield")) |is_bitfield| { if (!is_bitfield.bool) { @@ -693,16 +692,14 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { std.debug.assert(false); } - is_in_bitfield = true; - const inner_value_index = 0; // Not sure if this is always 0. const inner_value_elem = item_inner.?.array.items[inner_value_index]; const bitfield_field_bits_str = inner_value_elem.object.getPtr("value").?.string; bitfield_field_bits = try std.fmt.parseInt(u32, bitfield_field_bits_str, 10); - const bitfield_type_bytes = TypeToByteSizeLUT.get(item_type).?; + const bitfield_type_bytes = if (TypeToByteSizeLUT.has(item_type)) TypeToByteSizeLUT.get(item_type).? else 4; const bitfield_type_bits = bitfield_type_bytes * 8; - const bitfield_signed = TypeToSignedLUT.get(item_type).?; + const bitfield_signed = if (TypeToSignedLUT.has(item_type)) TypeToSignedLUT.get(item_type).? else false; const bitfield_type_changed = bitfield_type_bytes_curr == null or bitfield_type_bytes_curr.? != bitfield_type_bytes; const bitfield_sign_changed = bitfield_signed_curr != bitfield_signed; @@ -728,7 +725,7 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { bitfield_group += 1; try self.startBitfield(bitfield_group, bitfield_type_bits); bitfield_struct_bits_remaining = bitfield_type_bits; - } else if (is_in_bitfield and bitfield_struct_bits_remaining < bitfield_field_bits) { + } else if (bitfield_struct_bits_remaining < bitfield_field_bits) { // Existing bitfield but new field doesn't fit try self.finalizeBitfield(bitfield_struct_bits_remaining); @@ -736,11 +733,12 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { try self.startBitfield(bitfield_group, bitfield_type_bits); bitfield_struct_bits_remaining = bitfield_type_bits; } - } else { - is_in_bitfield = false; + } else if (bitfield_type_bytes_curr != null) { + try self.finalizeBitfield(bitfield_struct_bits_remaining); + bitfield_type_bytes_curr = null; } - const field_type = switch (is_in_bitfield) { + const field_type = switch (bitfield_type_bytes_curr != null) { true => blk: { bitfield_struct_bits_remaining -= bitfield_field_bits; break :blk try self.addBitfieldField(bitfield_signed_curr, bitfield_field_bits); @@ -752,7 +750,7 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { try self.out.print(" {s}: {s}", .{ field_name, field_type }); // field default value - if (item_inner != null and !is_in_bitfield) { + if (item_inner != null and bitfield_type_bytes_curr == null) { var value_exp = std.ArrayList(u8).init(self.allocator); defer value_exp.deinit(); @@ -826,8 +824,8 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { } } - if (is_in_bitfield) { - is_in_bitfield = false; + if (bitfield_type_bytes_curr != null) { + bitfield_type_bytes_curr = null; try self.finalizeBitfield(bitfield_struct_bits_remaining); } From 20ba62ba001bab2a306e90a8b1303f3f48934e38 Mon Sep 17 00:00:00 2001 From: Anders Elfgren Date: Sun, 10 Mar 2024 07:08:59 +0100 Subject: [PATCH 3/7] Fixed some bugs with bitfields and added test. --- src/Transpiler.zig | 17 ++++++++++------ test_cases/c024_cpp_bitfields.zig | 26 +++++++++++++++++++++++++ test_cases/c024_cpp_bitfields_glue.cpp | 4 ++++ test_cases/include/c024_cpp_bitfields.h | 12 ++++++++++++ 4 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 test_cases/c024_cpp_bitfields.zig create mode 100644 test_cases/c024_cpp_bitfields_glue.cpp create mode 100644 test_cases/include/c024_cpp_bitfields.h diff --git a/src/Transpiler.zig b/src/Transpiler.zig index 2b78c8a..845dada 100644 --- a/src/Transpiler.zig +++ b/src/Transpiler.zig @@ -681,6 +681,7 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { const item_inner = item.object.getPtr("inner"); const item_type = try self.transpileType(typeQualifier(item).?); defer self.allocator.free(item_type); + const bitfield_signed = if (TypeToSignedLUT.has(item_type)) TypeToSignedLUT.get(item_type).? else false; try self.writeDocs(item_inner); @@ -699,11 +700,11 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { const bitfield_type_bytes = if (TypeToByteSizeLUT.has(item_type)) TypeToByteSizeLUT.get(item_type).? else 4; const bitfield_type_bits = bitfield_type_bytes * 8; - const bitfield_signed = if (TypeToSignedLUT.has(item_type)) TypeToSignedLUT.get(item_type).? else false; - const bitfield_type_changed = bitfield_type_bytes_curr == null or bitfield_type_bytes_curr.? != bitfield_type_bytes; - const bitfield_sign_changed = bitfield_signed_curr != bitfield_signed; - if (bitfield_type_changed or bitfield_sign_changed) { + const bitfield_type_size_prev = if (bitfield_type_bytes_curr == null) 0 else bitfield_type_bytes_curr.?; + const bitfield_type_size_increased = bitfield_type_size_prev < bitfield_type_bytes; + const bitfield_sign_changed = false; // Actually fine to mix I think? bitfield_signed_curr != bitfield_signed; + if (bitfield_type_size_increased or bitfield_sign_changed) { // A new bitfield // - or - // Underlying type's size changed, need to start a new bitfield @@ -741,7 +742,7 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { const field_type = switch (bitfield_type_bytes_curr != null) { true => blk: { bitfield_struct_bits_remaining -= bitfield_field_bits; - break :blk try self.addBitfieldField(bitfield_signed_curr, bitfield_field_bits); + break :blk try self.addBitfieldField(bitfield_signed, bitfield_field_bits); }, false => try self.transpileType(typeQualifier(item).?), }; @@ -766,7 +767,11 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { } } - try self.out.print(",\n", .{}); + if (bitfield_type_bytes_curr != null) { + try self.out.print(", // {d} bits\n", .{bitfield_type_bytes_curr.? * 8 - bitfield_struct_bits_remaining}); + } else { + try self.out.print(",\n", .{}); + } } else if (mem.eql(u8, kind, "CXXMethodDecl")) { if (!self.public) continue; diff --git a/test_cases/c024_cpp_bitfields.zig b/test_cases/c024_cpp_bitfields.zig new file mode 100644 index 0000000..01d85b4 --- /dev/null +++ b/test_cases/c024_cpp_bitfields.zig @@ -0,0 +1,26 @@ +// auto generated by c2z +const std = @import("std"); +//const cpp = @import("cpp"); + +pub const Bitfields = extern struct { + bitfield_1: packed struct(u64) { + bitfield1: u10, // 10 bits + bitfield2: u10, // 20 bits + bitfield3: u5, // 25 bits + bitfield4: i5, // 30 bits + bitfield5: u2, // 32 bits + bitfield6: u2, // 34 bits + /// Padding added by c2z + _dummy_padding: u30, + }, + bitfield_2: packed struct(u32) { + bitfield7: i31, // 63 bits + /// Padding added by c2z + _dummy_padding: u1, + }, + bitfield_3: packed struct(u64) { + bitfield8: i30, // 30 bits + /// Padding added by c2z + _dummy_padding: u34, + }, +}; diff --git a/test_cases/c024_cpp_bitfields_glue.cpp b/test_cases/c024_cpp_bitfields_glue.cpp new file mode 100644 index 0000000..2cff0d8 --- /dev/null +++ b/test_cases/c024_cpp_bitfields_glue.cpp @@ -0,0 +1,4 @@ +// auto generated by c2z +#include +#include "c024_cpp_bitfields.h" + diff --git a/test_cases/include/c024_cpp_bitfields.h b/test_cases/include/c024_cpp_bitfields.h new file mode 100644 index 0000000..37bb146 --- /dev/null +++ b/test_cases/include/c024_cpp_bitfields.h @@ -0,0 +1,12 @@ +typedef struct Bitfields +{ + unsigned long long bitfield1 : 10; + unsigned long long bitfield2 : 10; + unsigned long bitfield3 : 5; + signed long bitfield4 : 5; + bool bitfield5 : 2; + char bitfield6 : 2; + unsigned char bitfield6 : 2; + int bitfield7 : 31; + long long bitfield8 : 30; +} Bitfields; From 6165f647fbe71862fcce601efd9402d89469c644 Mon Sep 17 00:00:00 2001 From: Anders Elfgren Date: Sun, 10 Mar 2024 09:50:18 +0100 Subject: [PATCH 4/7] Added bitfield test and fixed bug. --- build.zig | 2 ++ src/Transpiler.zig | 5 +-- test_cases/c024_cpp_bitfields.zig | 37 +++++++++++++++++------ test_cases/c024_cpp_bitfields_glue.cpp | 1 + test_cases/include/c024_cpp_bitfields.cpp | 5 +++ test_cases/include/c024_cpp_bitfields.h | 11 +++++-- test_cases/tests.zig | 7 +++++ 7 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 test_cases/include/c024_cpp_bitfields.cpp diff --git a/build.zig b/build.zig index adbbaa3..c11e4ce 100644 --- a/build.zig +++ b/build.zig @@ -77,6 +77,7 @@ pub fn build(b: *std.Build) void { lib.addCSourceFile(.{ .file = .{ .path = "./test_cases/include/c005_inheritance.cpp" }, .flags = cflags }); lib.addCSourceFile(.{ .file = .{ .path = "./test_cases/include/c013_cpp_vector.cpp" }, .flags = cflags }); lib.addCSourceFile(.{ .file = .{ .path = "./test_cases/include/c022_cpp_string.cpp" }, .flags = cflags }); + lib.addCSourceFile(.{ .file = .{ .path = "./test_cases/include/c024_cpp_bitfields.cpp" }, .flags = cflags }); // glue //lib.addCSourceFile("./test_cases/c001_c_structs_glue.cpp", cflags); lib.addCSourceFile(.{ .file = .{ .path = "./test_cases/c005_inheritance_glue.cpp" }, .flags = cflags }); @@ -84,6 +85,7 @@ pub fn build(b: *std.Build) void { lib.addCSourceFile(.{ .file = .{ .path = "./test_cases/c011_index_this_glue.cpp" }, .flags = cflags }); lib.addCSourceFile(.{ .file = .{ .path = "./test_cases/c013_cpp_vector_glue.cpp" }, .flags = cflags }); lib.addCSourceFile(.{ .file = .{ .path = "./test_cases/c022_cpp_string_glue.cpp" }, .flags = cflags }); + lib.addCSourceFile(.{ .file = .{ .path = "./test_cases/c024_cpp_bitfields_glue.cpp" }, .flags = cflags }); test_cases.linkLibrary(lib); const cpp_mod = b.addModule("cpp", .{ .root_source_file = .{ .path = "src/cpp.zig" } }); diff --git a/src/Transpiler.zig b/src/Transpiler.zig index 845dada..314a69a 100644 --- a/src/Transpiler.zig +++ b/src/Transpiler.zig @@ -701,10 +701,11 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { const bitfield_type_bytes = if (TypeToByteSizeLUT.has(item_type)) TypeToByteSizeLUT.get(item_type).? else 4; const bitfield_type_bits = bitfield_type_bytes * 8; + // TODO: Need to handle 0-length (unnamed) bitfields (used for re-aligning next field) const bitfield_type_size_prev = if (bitfield_type_bytes_curr == null) 0 else bitfield_type_bytes_curr.?; - const bitfield_type_size_increased = bitfield_type_size_prev < bitfield_type_bytes; + const bitfield_type_size_changed = bitfield_type_size_prev != bitfield_type_bytes; const bitfield_sign_changed = false; // Actually fine to mix I think? bitfield_signed_curr != bitfield_signed; - if (bitfield_type_size_increased or bitfield_sign_changed) { + if (bitfield_type_size_changed or bitfield_sign_changed) { // A new bitfield // - or - // Underlying type's size changed, need to start a new bitfield diff --git a/test_cases/c024_cpp_bitfields.zig b/test_cases/c024_cpp_bitfields.zig index 01d85b4..d9ebd0f 100644 --- a/test_cases/c024_cpp_bitfields.zig +++ b/test_cases/c024_cpp_bitfields.zig @@ -6,21 +6,40 @@ pub const Bitfields = extern struct { bitfield_1: packed struct(u64) { bitfield1: u10, // 10 bits bitfield2: u10, // 20 bits - bitfield3: u5, // 25 bits - bitfield4: i5, // 30 bits - bitfield5: u2, // 32 bits - bitfield6: u2, // 34 bits + /// C2Z WARNING: This perhaps shouldn't be padded in this way! /// Padding added by c2z - _dummy_padding: u30, + _dummy_padding: u44, }, bitfield_2: packed struct(u32) { - bitfield7: i31, // 63 bits + bitfield3: u5, // 5 bits + bitfield4: i5, // 10 bits + /// C2Z WARNING: This perhaps shouldn't be padded in this way! + /// Padding added by c2z + _dummy_padding: u22, + }, + bitfield_3: packed struct(u8) { + bitfield5: u2, // 2 bits + bitfield6: u2, // 4 bits + bitfield7: u2, // 6 bits + /// C2Z WARNING: This perhaps shouldn't be padded in this way! + /// Padding added by c2z + _dummy_padding: u2, + }, + bitfield_4: packed struct(u32) { + bitfield8: i31, // 31 bits + /// C2Z WARNING: This perhaps shouldn't be padded in this way! /// Padding added by c2z _dummy_padding: u1, }, - bitfield_3: packed struct(u64) { - bitfield8: i30, // 30 bits + bitfield_5: packed struct(u64) { + bitfield9: i30, // 30 bits + /// TODO: Add test of 0-length bitfield here + /// long long : 0; + bitfield11: i30, // 60 bits /// Padding added by c2z - _dummy_padding: u34, + _dummy_padding: u4, }, }; + +extern fn _1_size_of_Bitfields_() c_int; +pub const size_of_Bitfields = _1_size_of_Bitfields_; diff --git a/test_cases/c024_cpp_bitfields_glue.cpp b/test_cases/c024_cpp_bitfields_glue.cpp index 2cff0d8..27e46b8 100644 --- a/test_cases/c024_cpp_bitfields_glue.cpp +++ b/test_cases/c024_cpp_bitfields_glue.cpp @@ -2,3 +2,4 @@ #include #include "c024_cpp_bitfields.h" +extern "C" int _1_size_of_Bitfields_() { return ::size_of_Bitfields(); } diff --git a/test_cases/include/c024_cpp_bitfields.cpp b/test_cases/include/c024_cpp_bitfields.cpp new file mode 100644 index 0000000..89a4214 --- /dev/null +++ b/test_cases/include/c024_cpp_bitfields.cpp @@ -0,0 +1,5 @@ +#include "c024_cpp_bitfields.h" + +int size_of_Bitfields(){ + return sizeof(Bitfields); +} diff --git a/test_cases/include/c024_cpp_bitfields.h b/test_cases/include/c024_cpp_bitfields.h index 37bb146..79b97f0 100644 --- a/test_cases/include/c024_cpp_bitfields.h +++ b/test_cases/include/c024_cpp_bitfields.h @@ -6,7 +6,12 @@ typedef struct Bitfields signed long bitfield4 : 5; bool bitfield5 : 2; char bitfield6 : 2; - unsigned char bitfield6 : 2; - int bitfield7 : 31; - long long bitfield8 : 30; + unsigned char bitfield7 : 2; + int bitfield8 : 31; + long long bitfield9 : 30; + // TODO: Add test of 0-length bitfield here + // long long : 0; + long long bitfield11 : 30; } Bitfields; + +int size_of_Bitfields(); diff --git a/test_cases/tests.zig b/test_cases/tests.zig index 92433e7..1bc73b2 100644 --- a/test_cases/tests.zig +++ b/test_cases/tests.zig @@ -112,4 +112,11 @@ test "cpp_string" { // buffer.deinit(); // this doesn't // //buffer = cpp.String.init(.{}); // this leaks memory // } + +test "cpp_bitfields" { + const fii = @import("c024_cpp_bitfields.zig"); + + const zig_size_bitfields = @as(c_int, @sizeOf(fii.Bitfields)); + const cpp_size_bitfields = fii.size_of_Bitfields(); + try expectEqual(zig_size_bitfields, cpp_size_bitfields); } From e1930bdc11acc230fcebc30c76a6cf5906a4e18e Mon Sep 17 00:00:00 2001 From: Anders Elfgren Date: Mon, 11 Mar 2024 09:42:20 +0100 Subject: [PATCH 5/7] Added missing brace. --- test_cases/tests.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/test_cases/tests.zig b/test_cases/tests.zig index 1bc73b2..a427517 100644 --- a/test_cases/tests.zig +++ b/test_cases/tests.zig @@ -112,6 +112,7 @@ test "cpp_string" { // buffer.deinit(); // this doesn't // //buffer = cpp.String.init(.{}); // this leaks memory // } +} test "cpp_bitfields" { const fii = @import("c024_cpp_bitfields.zig"); From b33057acf0a2e70f60461832b093c9bf70ccea24 Mon Sep 17 00:00:00 2001 From: Anders Elfgren Date: Mon, 11 Mar 2024 10:49:36 +0100 Subject: [PATCH 6/7] Bitfield test now only runs on windows. --- src/Transpiler.zig | 1 + test_cases/tests.zig | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Transpiler.zig b/src/Transpiler.zig index 314a69a..ba49fb9 100644 --- a/src/Transpiler.zig +++ b/src/Transpiler.zig @@ -851,6 +851,7 @@ fn visitCXXRecordDecl(self: *Self, value: *const json.Value) !void { fn startBitfield(self: *Self, bitfield_group: u32, bitfield_type_bits: u32) !void { try self.out.print(" bitfield_{d}: packed struct(u{d}) {{\n", .{ bitfield_group, bitfield_type_bits }); + try self.out.print(" // NOTE: Bitfield generation not guaranteed to work on all platforms, use with caution. \n\n", .{}); } fn addBitfieldField(self: *Self, is_signed: bool, bitfield_field_bits: u32) ![]u8 { diff --git a/test_cases/tests.zig b/test_cases/tests.zig index a427517..e8759fe 100644 --- a/test_cases/tests.zig +++ b/test_cases/tests.zig @@ -117,7 +117,10 @@ test "cpp_string" { test "cpp_bitfields" { const fii = @import("c024_cpp_bitfields.zig"); - const zig_size_bitfields = @as(c_int, @sizeOf(fii.Bitfields)); - const cpp_size_bitfields = fii.size_of_Bitfields(); - try expectEqual(zig_size_bitfields, cpp_size_bitfields); + if (std.builtin.os.tag == .windows) { + // TODO: Improved support for bitfields. + const zig_size_bitfields = @as(c_int, @sizeOf(fii.Bitfields)); + const cpp_size_bitfields = fii.size_of_Bitfields(); + try expectEqual(zig_size_bitfields, cpp_size_bitfields); + } } From 26c5b3762dc951acbcc9ad2d4324f58d771d1c6f Mon Sep 17 00:00:00 2001 From: Anders Elfgren Date: Tue, 12 Mar 2024 05:15:00 +0100 Subject: [PATCH 7/7] Compile fix for test. --- test_cases/tests.zig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test_cases/tests.zig b/test_cases/tests.zig index e8759fe..f3d3568 100644 --- a/test_cases/tests.zig +++ b/test_cases/tests.zig @@ -117,10 +117,11 @@ test "cpp_string" { test "cpp_bitfields" { const fii = @import("c024_cpp_bitfields.zig"); - if (std.builtin.os.tag == .windows) { + if (@import("builtin").os.tag == .windows) { // TODO: Improved support for bitfields. const zig_size_bitfields = @as(c_int, @sizeOf(fii.Bitfields)); const cpp_size_bitfields = fii.size_of_Bitfields(); try expectEqual(zig_size_bitfields, cpp_size_bitfields); } } +