File tree Expand file tree Collapse file tree 4 files changed +74
-7
lines changed
Expand file tree Collapse file tree 4 files changed +74
-7
lines changed Original file line number Diff line number Diff line change @@ -13,6 +13,7 @@ endif ()
1313set (TESTS
1414 alias.m
1515 alignTest.m
16+ bitfield.m
1617 AllocatePair.m
1718 AssociatedObject.m
1819 AssociatedObject2.m
Original file line number Diff line number Diff line change @@ -89,9 +89,18 @@ int main(int argc, char *argv[])
8989 assert (ivar_getOffset (c3) == baseSmallOffset + 4 );
9090 assert (ivar_getOffset (b1) == baseSmallOffset + 2 );
9191 assert (ivar_getOffset (b2) == baseSmallOffset + 2 );
92- assert (ivar_getOffset (b3) == baseSmallOffset + 3 );
93- assert (ivar_getOffset (b4) == baseSmallOffset + 3 );
94- assert (ivar_getOffset (notBitfield) == baseSmallOffset + 4 );
92+ // These could be tighter, but the way that clang currently emits ivars for
93+ // bitfields is a bit odd. Unfortunately, it sometimes adds a small
94+ // displacement so that it can load individual words, but the metadata
95+ // doesn't tell us anything about them. Fixing this would require using an
96+ // extra metadata flag or similar to indicate that the size of the ivar is
97+ // not the storage size.
98+ assert ((ivar_getOffset (b3) == baseSmallOffset + 3 ) ||
99+ (ivar_getOffset (b3) == baseSmallOffset + 4 ));
100+ assert ((ivar_getOffset (b4) == baseSmallOffset + 3 ) ||
101+ (ivar_getOffset (b4) == baseSmallOffset + 4 ));
102+ assert ((ivar_getOffset (notBitfield) == baseSmallOffset + 4 ) ||
103+ (ivar_getOffset (notBitfield) == baseSmallOffset + 6 ));
95104#endif
96105
97106
Original file line number Diff line number Diff line change 1+ #include " stdio.h"
2+ #include " Test.h"
3+ #include " objc/runtime.h"
4+ #include " objc/encoding.h"
5+
6+ @interface Bitfield : Test
7+ {
8+ unsigned short first;
9+ unsigned isShip: 1 ,
10+ isStation: 1 ;
11+ unsigned y;
12+ }
13+
14+ @end
15+ @implementation Bitfield
16+ - (BOOL )isShip { return isShip; }
17+ - (BOOL )isStation { return isStation; }
18+ - (void )setShip : (BOOL )aValue
19+ {
20+ isShip = aValue;
21+ }
22+ - (void )setStation : (BOOL )aValue
23+ {
24+ isStation = aValue;
25+ }
26+ - (void )setY : (int )anInt
27+ {
28+ y = anInt;
29+ }
30+ @end
31+
32+ static size_t offset (const char *ivar)
33+ {
34+ return ivar_getOffset (class_getInstanceVariable ([Bitfield class ], ivar));
35+ }
36+
37+ static size_t size (const char *ivar)
38+ {
39+ return objc_sizeof_type (ivar_getTypeEncoding (class_getInstanceVariable ([Bitfield class ], ivar)));
40+ }
41+
42+ int main (void )
43+ {
44+ Bitfield *bf = [Bitfield new ];
45+ assert (![bf isShip ]);
46+ assert (![bf isStation ]);
47+ [bf setShip: YES ];
48+ assert ([bf isShip ]);
49+ assert (![bf isStation ]);
50+ [bf setStation: YES ];
51+ [bf setY: 0 ];
52+ assert ([bf isShip ]);
53+ assert ([bf isStation ]);
54+ assert (offset (" isShip" ) >= offset (" first" ) + size (" first" ));
55+ assert (offset (" isShip" ) == offset (" isStation" ));
56+ assert (offset (" y" ) >= offset (" isStation" ) + size (" isStation" ));
57+ }
Original file line number Diff line number Diff line change @@ -85,25 +85,25 @@ PRIVATE void objc_compute_ivar_offsets(Class class)
8585 // that contains them. If we are in a bitfield, then we need
8686 // to make sure that we don't add any displacement from the
8787 // previous value.
88- if (* ivar -> offset < last_offset + last_size )
88+ if (( i != 0 ) && ( * ivar -> offset == last_offset ) )
8989 {
90- * ivar -> offset = last_computed_offset + (* ivar -> offset - last_offset );
91- ivar_size = 0 ;
90+ * ivar -> offset = last_computed_offset ;
9291 continue ;
9392 }
9493 last_offset = * ivar -> offset ;
9594 * ivar -> offset = next_ivar ;
96- last_computed_offset = * ivar -> offset ;
9795 next_ivar += ivar_size ;
9896 last_size = ivar -> size ;
9997 size_t align = ivarGetAlign (ivar );
98+ // If the alignment is insufficient, round it up.
10099 if ((* ivar -> offset + refcount_size ) % align != 0 )
101100 {
102101 long padding = align - ((* ivar -> offset + refcount_size ) % align );
103102 * ivar -> offset += padding ;
104103 class -> instance_size += padding ;
105104 next_ivar += padding ;
106105 }
106+ last_computed_offset = * ivar -> offset ;
107107 assert ((* ivar -> offset + sizeof (uintptr_t )) % ivarGetAlign (ivar ) == 0 );
108108 class -> instance_size += ivar_size ;
109109 }
You can’t perform that action at this time.
0 commit comments