Skip to content

Commit

Permalink
RECONSIDER: Working around a WinObjC regression that hit after switch…
Browse files Browse the repository at this point in the history
…ing to the libobjc2 runtime

Clang occasionally emits a negative offest for the first ivar in a subclass. When that occurs, we need to increase the padding between the superclass and the subclass by that amount to prevent ivars from stomping each other.

This is a temporary workaround until we can fix this in clang; not intended for upstream consumption.
  • Loading branch information
jaredhms authored and DHowett committed Jan 22, 2018
1 parent c8ecc35 commit c2013dc
Showing 1 changed file with 28 additions and 1 deletion.
29 changes: 28 additions & 1 deletion ivar.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ PRIVATE void objc_compute_ivar_offsets(Class class)
ivar_start = super->instance_size;
}
long class_size = 0 - class->instance_size;
class->instance_size = ivar_start - class->instance_size;

/* For each instance variable, we add the offset if required (it will be zero
* if this class is compiled with a static ivar layout). We then set the
* value of a global variable to the offset value.
Expand All @@ -56,6 +56,29 @@ PRIVATE void objc_compute_ivar_offsets(Class class)
long ivar_size = (i+1 == class->ivars->count)
? (class_size - ivar->offset)
: ivar->offset - class->ivars->ivar_list[i+1].offset;

// TODO: Working around a WinObjC regression that hit after switching to the libobjc2 runtime.
// Clang occasionally emits a negative offest for the first ivar in a subclass.
// When that occurs, we need to increase the padding between the superclass and the subclass by that amount to prevent ivars from stomping each other.
// This is a temporary workaround until we can fix this in clang; not intended for upstream consumption.
if (ivar->offset < 0) {
if (i != 0) {
// We only expect to see negative offsets for the *first* ivar in a class.
fprintf(stderr,
"Error: Class %hs has an unexpected ivar %hs with a negative offset of %d!\n",
class->name,
ivar->name,
ivar->offset);
abort();
}

printf("Warning: Class %hs has first ivar %hs with a negative offset of %d!\n",
class->name,
ivar->name,
ivar->offset);
ivar_start += -(ivar->offset);
}

#if 0
// We only need to do the realignment for things that are
// bigger than a pointer, and we don't need to do it in GC mode
Expand Down Expand Up @@ -90,6 +113,10 @@ PRIVATE void objc_compute_ivar_offsets(Class class)
}
}
}

// TODO: Move this back under line 34 once the TODO above is fixed.
// Update the instance_size to account for any adjustment to the ivar layout
class->instance_size = ivar_start - class->instance_size;
}
else
{
Expand Down

0 comments on commit c2013dc

Please sign in to comment.