Skip to content

[Swift 3.0] Fix s390x Enum load/storeMultiPayloadValue #4463

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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
14 changes: 11 additions & 3 deletions stdlib/public/runtime/Enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,17 +348,25 @@ static void storeMultiPayloadValue(OpaqueValue *value,
#if defined(__BIG_ENDIAN__)
unsigned numPayloadValueBytes =
std::min(layout.payloadSize, sizeof(payloadValue));
memcpy(bytes,
memcpy(bytes + sizeof(OpaqueValue *) - numPayloadValueBytes,
reinterpret_cast<char *>(&payloadValue) + 4 - numPayloadValueBytes,
numPayloadValueBytes);
if (layout.payloadSize > sizeof(payloadValue) &&
layout.payloadSize > sizeof(OpaqueValue *)) {
memset(bytes, 0,
sizeof(OpaqueValue *) - numPayloadValueBytes);
memset(bytes + sizeof(OpaqueValue *), 0,
layout.payloadSize - sizeof(OpaqueValue *));
}
#else
memcpy(bytes, &payloadValue,
std::min(layout.payloadSize, sizeof(payloadValue)));
#endif

// If the payload is larger than the value, zero out the rest.
if (layout.payloadSize > sizeof(payloadValue))
memset(bytes + sizeof(payloadValue), 0,
layout.payloadSize - sizeof(payloadValue));
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The #endif is now after the code that would previously had been available when __BIG_ENDIAN__ is not defined. Is this change intended?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also clearly a behavioral change here, but no test case reflecting that. I don't accepting this change would be acceptable for the swift-3.0-branch in the current state without a test case. It's also not clear to me if the change is correct, per my comment about the preprocessor guard.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review.

The code from lines 365-368 are still available when __BIG_ENDIAN__ is not defined (as they are between #else and #endif). Nothing has changed for little endian platforms.

The Interpreter/enum.swift test was failing on s390x and is now passing with this change. We didn't observe any regression in other tests with this change.

@garyliu1, FYI

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Further explaining the move of the #endif...

The new code between line 354-360 is the corresponding memset work required for big endian platforms. Therefore, the original memset code (which was common before) would need to be made specific for little endian platforms or else the big endian platform would perform another memset and corrupt the existing data.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You both are absolutely right. Sorry for misreading the code. This looks perfectly safe to take.

}

static unsigned loadMultiPayloadTag(const OpaqueValue *value,
Expand All @@ -384,7 +392,7 @@ static unsigned loadMultiPayloadValue(const OpaqueValue *value,
unsigned numPayloadValueBytes =
std::min(layout.payloadSize, sizeof(payloadValue));
memcpy(reinterpret_cast<char *>(&payloadValue) + 4 - numPayloadValueBytes,
bytes, numPayloadValueBytes);
bytes + sizeof(OpaqueValue *) - numPayloadValueBytes, numPayloadValueBytes);
#else
memcpy(&payloadValue, bytes,
std::min(layout.payloadSize, sizeof(payloadValue)));
Expand Down