-
-
Notifications
You must be signed in to change notification settings - Fork 613
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix bugzilla 24592 - ImportC: Bitfield layout wrong for int64 on 32-b…
…it Linux Type ulong is 64-bit on 32-bit Linux, but has 32-bit alignment. This affects the layout of bitfields. Also add a new test for ImportC bitfields, which compares size, alignment and layout with the host C++ compiler. The existing tests compared with fixed values instead.
- Loading branch information
Showing
7 changed files
with
257 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
compiler/test/runnable_cxx/extra-files/testbitfields_cpp.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
extern "C" | ||
{ | ||
#include "testbitfields_importc.c" | ||
} | ||
|
||
#include <stdio.h> | ||
#include <string.h> | ||
|
||
template<typename T> | ||
size_t getStructSize(); | ||
template<typename T> | ||
size_t getStructAlign(); | ||
template<typename T> | ||
void resetBitfield(T &data, const char *member); | ||
|
||
#define BEGIN_STRUCT(S) \ | ||
template<> \ | ||
size_t getStructSize<S>() \ | ||
{ \ | ||
return sizeof(S); \ | ||
} \ | ||
template<> \ | ||
size_t getStructAlign<S>() \ | ||
{ \ | ||
return alignof(S); \ | ||
} \ | ||
template<> \ | ||
void resetBitfield<S>(S &data, const char *member) \ | ||
{ | ||
|
||
#define FIELD(name) if (strcmp(member, #name) == 0) data.name = 0; | ||
#define END_STRUCT } | ||
|
||
BEGIN_STRUCT(T0) FIELD(x) END_STRUCT | ||
BEGIN_STRUCT(T1) FIELD(x) END_STRUCT | ||
BEGIN_STRUCT(T2) FIELD(x) END_STRUCT | ||
BEGIN_STRUCT(T3) FIELD(a) FIELD(b) FIELD(c) FIELD(d) FIELD(x) END_STRUCT | ||
BEGIN_STRUCT(T4) FIELD(a) FIELD(b) FIELD(c) FIELD(d) FIELD(e) FIELD(f) FIELD(g) FIELD(h) FIELD(x) END_STRUCT | ||
BEGIN_STRUCT(T5) FIELD(a) FIELD(b) FIELD(c) FIELD(d) FIELD(e) FIELD(f) FIELD(g) FIELD(x) END_STRUCT | ||
BEGIN_STRUCT(S1) FIELD(f) END_STRUCT | ||
BEGIN_STRUCT(S2) FIELD(x) FIELD(y) END_STRUCT | ||
BEGIN_STRUCT(S3) FIELD(c) FIELD(x) FIELD(y) END_STRUCT | ||
BEGIN_STRUCT(S4) FIELD(x) FIELD(y) END_STRUCT | ||
BEGIN_STRUCT(S5) FIELD(x) FIELD(y) END_STRUCT | ||
BEGIN_STRUCT(S6) FIELD(x) FIELD(y) END_STRUCT | ||
BEGIN_STRUCT(S7) FIELD(x) FIELD(y) FIELD(z) END_STRUCT | ||
BEGIN_STRUCT(S8) FIELD(a) FIELD(b) FIELD(c) END_STRUCT | ||
BEGIN_STRUCT(S8A) FIELD(b) FIELD(c) END_STRUCT | ||
BEGIN_STRUCT(S8B) FIELD(a) FIELD(b) FIELD(c) END_STRUCT | ||
BEGIN_STRUCT(S8C) FIELD(a) FIELD(b) END_STRUCT | ||
BEGIN_STRUCT(S9) FIELD(a) FIELD(b) FIELD(c) END_STRUCT | ||
//BEGIN_STRUCT(S10) END_STRUCT | ||
//BEGIN_STRUCT(S11) END_STRUCT | ||
BEGIN_STRUCT(S12) FIELD(x) END_STRUCT | ||
BEGIN_STRUCT(S13) FIELD(x) FIELD(x1) FIELD(x2) FIELD(x3) FIELD(x4) FIELD(w) END_STRUCT | ||
BEGIN_STRUCT(S14) FIELD(a) FIELD(b) FIELD(c) END_STRUCT | ||
BEGIN_STRUCT(S15) FIELD(a) FIELD(b) FIELD(c) END_STRUCT | ||
BEGIN_STRUCT(S16) END_STRUCT | ||
BEGIN_STRUCT(S17) FIELD(a) END_STRUCT | ||
BEGIN_STRUCT(S18) FIELD(a) FIELD(b) END_STRUCT | ||
BEGIN_STRUCT(A0) FIELD(a) FIELD(b) FIELD(c) END_STRUCT | ||
BEGIN_STRUCT(A1) FIELD(a) FIELD(b) FIELD(c) END_STRUCT | ||
BEGIN_STRUCT(A2) FIELD(a) FIELD(b) FIELD(c) FIELD(d) | ||
FIELD(e) END_STRUCT | ||
BEGIN_STRUCT(A3) FIELD(a) FIELD(b) FIELD(c) FIELD(d) | ||
FIELD(e) END_STRUCT | ||
BEGIN_STRUCT(A4) FIELD(a) FIELD(b) | ||
FIELD(c) END_STRUCT | ||
BEGIN_STRUCT(A5) FIELD(a) FIELD(b) END_STRUCT | ||
BEGIN_STRUCT(A6) FIELD(a) FIELD(b) END_STRUCT | ||
BEGIN_STRUCT(A7) FIELD(a) FIELD(b) FIELD(c) | ||
FIELD(d) END_STRUCT | ||
BEGIN_STRUCT(A8) FIELD(a) FIELD(b) | ||
FIELD(c) END_STRUCT | ||
BEGIN_STRUCT(A9) FIELD(a) FIELD(b) | ||
FIELD(c) FIELD(d) | ||
FIELD(e) FIELD(f) END_STRUCT | ||
BEGIN_STRUCT(A10) FIELD(a) FIELD(b) END_STRUCT | ||
BEGIN_STRUCT(A11) FIELD(a) FIELD(b) FIELD(c) FIELD(d) | ||
END_STRUCT | ||
BEGIN_STRUCT(Issue24592a) FIELD(a) FIELD(b) FIELD(c) END_STRUCT | ||
BEGIN_STRUCT(Issue24592b) FIELD(x) FIELD(a) FIELD(b) FIELD(c) END_STRUCT | ||
BEGIN_STRUCT(Issue24592c) FIELD(a) FIELD(b) FIELD(c) FIELD(d) FIELD(e) FIELD(f) END_STRUCT | ||
BEGIN_STRUCT(Issue24592d) FIELD(a) FIELD(b) FIELD(c) FIELD(d) FIELD(e) FIELD(f) END_STRUCT |
52 changes: 52 additions & 0 deletions
52
compiler/test/runnable_cxx/extra-files/testbitfields_importc.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
|
||
struct T0 { char x:1; }; | ||
struct T1 { short x:1; }; | ||
struct T2 { int x:1; }; | ||
struct T3 { char a,b,c,d; long long x:1; }; | ||
struct T4 { char a,b,c,d,e,f,g,h; long long x:1; }; | ||
struct T5 { char a,b,c,d,e,f,g; long long x:1; }; | ||
struct S1 { long long int f:1; }; | ||
struct S2 { int x:1; int y:1; }; | ||
struct S3 { short c; int x:1; unsigned y:1; }; | ||
struct S4 { int x:1; short y:1; }; | ||
struct S5 { short x:1; int y:1; }; | ||
struct S6 { short x:1; short y:1; }; | ||
struct S7 { short x:1; int y:1; long long z:1; }; | ||
struct S8 { char a; char b:1; short c:2; }; | ||
struct S8A { char b:1; short c:2; }; | ||
struct S8B { char a; short b:1; char c:2; }; | ||
struct S8C { char a; int b:1; }; | ||
struct S9 { char a; char b:2; short c:9; }; | ||
//struct S10 { }; | ||
//struct S11 { int :0; }; | ||
struct S12 { int :0; int x; }; | ||
struct S13 { unsigned x:12; unsigned x1:1; unsigned x2:1; unsigned x3:1; unsigned x4:1; int w; }; | ||
struct S14 { char a; char b:4; int c:30; }; | ||
struct S15 { char a; char b:2; int c:9; }; | ||
struct S16 { int :32; }; | ||
struct S17 { int a:32; }; | ||
struct S18 { char a; long long :0; char b; }; | ||
struct A0 { int a; long long b:34, c:4; }; | ||
struct A1 { int a; unsigned b:11; int c; }; | ||
struct A2 { int a; unsigned b:11, c:5, d:16; | ||
int e; }; | ||
struct A3 { int a; unsigned b:11, c:5, :0, d:16; | ||
int e; }; | ||
struct A4 { int a:8; short b:7; | ||
unsigned int c:29; }; | ||
struct A5 { char a:7, b:2; }; | ||
struct A6 { char a:7; short b:2; }; | ||
struct A7 { short a:8; long b:16; int c; | ||
char d:7; }; | ||
struct A8 { short a:8; long b:16; int :0; | ||
char c:7; }; | ||
struct A9 { unsigned short a:8; long b:16; | ||
unsigned long c:29; long long d:9; | ||
unsigned long e:2, f:31; }; | ||
struct A10 { unsigned short a:8; char b; }; | ||
struct A11 { char a; int b:5, c:11, :0, d:8; | ||
struct { int ee:8; } e; }; | ||
struct Issue24592a { unsigned long long a:20, b:20, c:24; }; | ||
struct Issue24592b { unsigned int x; unsigned long long a:20, b:20, c:24; }; | ||
struct Issue24592c { unsigned long long a:20, b:32, c:32, d:32, e:32, f:32; }; | ||
struct Issue24592d { unsigned long long a:10, b:16, c:16, d:16, e:16, f:16; }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// EXTRA_CPP_SOURCES: testbitfields_cpp.cpp | ||
// EXTRA_SOURCES: extra-files/testbitfields_importc.c | ||
// CXXFLAGS(linux osx freebsd dragonflybsd): -std=c++11 | ||
|
||
import core.stdc.stdio; | ||
import core.stdc.stdlib; | ||
import core.stdc.string; | ||
|
||
static import testbitfields_importc; | ||
|
||
extern(C++) size_t getStructSize(T)(); | ||
extern(C++) size_t getStructAlign(T)(); | ||
extern(C++) void resetBitfield(T)(ref T data, const(char) *member); | ||
|
||
bool checkType(S)() | ||
{ | ||
bool different; | ||
if (S.sizeof != getStructSize!S) | ||
different = true; | ||
if (S.alignof != getStructAlign!S) | ||
different = true; | ||
static foreach (member; __traits(allMembers, S)) | ||
{{ | ||
static if (member[0] != '_' && typeof(__traits(getMember, S, member)).stringof[0] != '_') | ||
{ | ||
S dummyD; | ||
memset(&dummyD, 0xff, S.sizeof); | ||
__traits(getMember, dummyD, member) = 0; | ||
|
||
S* dummyC = cast(S*) malloc(getStructSize!S); | ||
memset(dummyC, 0xff, getStructSize!S); | ||
resetBitfield!S(*dummyC, member.ptr); | ||
if (S.sizeof == getStructSize!S && memcmp(&dummyD, dummyC, S.sizeof) != 0) | ||
different = true; | ||
free(dummyC); | ||
} | ||
}} | ||
if (different) | ||
{ | ||
printf("Struct %s has different bitfield layout for C and D:\n", __traits(identifier, S).ptr); | ||
printf(" D: size=%zd align=%zd\n", S.sizeof, S.alignof); | ||
printf(" C: size=%zd align=%zd\n", getStructSize!S, getStructAlign!S); | ||
static foreach (member; __traits(allMembers, S)) | ||
{{ | ||
static if (member[0] != '_' && typeof(__traits(getMember, S, member)).stringof[0] != '_') | ||
{ | ||
printf(" %s %s:\n", typeof(__traits(getMember, S, member)).stringof.ptr, member.ptr); | ||
printf(" D:"); | ||
S dummyD; | ||
memset(&dummyD, 0xff, S.sizeof); | ||
__traits(getMember, dummyD, member) = 0; | ||
foreach (i; 0 .. S.sizeof) | ||
{ | ||
if (i % 4 == 0) | ||
printf(" "); | ||
printf("%02X", 0xff & ~(cast(ubyte*) &dummyD)[i]); | ||
} | ||
|
||
printf("\n C:"); | ||
S* dummyC = cast(S*) malloc(getStructSize!S); | ||
memset(dummyC, 0xff, getStructSize!S); | ||
resetBitfield!S(*dummyC, member.ptr); | ||
foreach (i; 0 .. getStructSize!S) | ||
{ | ||
if (i % 4 == 0) | ||
printf(" "); | ||
printf("%02X", 0xff & ~(cast(ubyte*) dummyC)[i]); | ||
} | ||
free(dummyC); | ||
printf("\n"); | ||
} | ||
}} | ||
} | ||
return different; | ||
} | ||
|
||
int main() | ||
{ | ||
int ret; | ||
static foreach (name; __traits(allMembers, testbitfields_importc)) | ||
{{ | ||
alias S = __traits(getMember, testbitfields_importc, name); | ||
static if (is(S == struct) && name[0] != '_') | ||
{ | ||
if (checkType!S) | ||
ret = 1; | ||
} | ||
}} | ||
return ret; | ||
} |