-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[clang] LazyOffsetPtr: Use native pointer width #111995
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
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may not be correct. The offset is required to be a 64 bit integer while the higher 32 bits are meaningful. Is there any ideas to make it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can the higher 32 bits be meaningful on a system whose pointers are 32 bits in length? Put another way: in what situation is a 64-bit offset to a 32-bit pointer valid?
The original message warns about 63 bits because the last bit is needed to tag the value as not-a-pointer (and as an offset). That doesn't mean values passed here have to be 63 bits in length, just that the (naive) implementation that hardcoded 64-bit size for pointers required the offset to fit in N-1 = 63 bits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it's an abstract offset, not a pointer offset.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we mmap the whole of each module file, so we definitely can't have more than 4GiB of module file data if the host has 32-bit pointers. But
Offset
here is in bits, and with 31 bits of offset, that only covers 256MiB of module data, which is a plausible and reasonable total file size for.pcm
files even when compiling on a 32-bit host. So I think we do want a 64-bit offset here even on a 32-bit system.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. But it is still invalid to
reinterpret_cast
auint64_t
to a pointer on 32-bit BE systems, and that would still leave that as a segfault.C++23 draft N4950, §7.6.1.10 number 5:
uint64_t is not the sufficient size for a 32-bit BE system. How should we proceed?
uint64_t Offset
and auintptr_t Ptr
), but that would unconditionally add 8 bytes perLazyOffsetPtr
. I'm not completely familiar with how many liveLazyOffsetPtr
objects might be present in a single invocation of Clang and how that would affect memory usage.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 32-bit PPC issue is presumably solved by just adding an intermediate cast.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's not. Please re-read the problem description. Casts in the LazyOffsetPtr implementation aren't going to fix anything. The problem is that getAddressOfPointer pretends that the underlying storage is a pointer, when it's really a uint64_t, and on a 32-bit big-endian system
*(void **)&my_uint64 = p
andmy_uint64 = (uint64_t)(uintptr_t)p
store the contents ofp
in different halves ofmy_uint64
(and zero the other half in the latter, but that isn't what's causing a problem). If you wanted to do something really disgusting you could implementgetAddressOfPointer
asreturn (T **)&Ptr + 1
, I suppose. But ideally we wouldn't be doing anything as highly dodgy when it comes to strict aliasing as that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, so the existence of a function that returns the address of internal storage is obviously always going to make abstraction very difficult. The perfectly portable way to write this is to use a union and a separate bool, and the whole point of this type is that that's a very inefficient way to store this information; we want it to be more compact, and we're willing to accept some non-portable assumptions to get that. So that's why I think the key question is whether we can change the clients to remove the need for
getAddressOfPointer
first. Once we do that, the rest of this becomes significantly more trivial.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If not, you probably need something like:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for misleading. The current decoding for
GlobalDeclID
(64 bits) is to split it as {ModuleFileIndex : 32, DeclIndex : 32}. And bothModuleFileIndex
andDeclIndex
starts from 0 to higher values. So it is safe to remove the highest bit of (ModuleFileIndex) by paying the price that upper bound of the number of modules in a single compilation to be only 2^31, which is a reasonable number.