-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
[IR] Require that ptrmask mask matches pointer index size #69343
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -26952,7 +26952,8 @@ Arguments: | |||||||||||
"""""""""" | ||||||||||||
|
||||||||||||
The first argument is a pointer or vector of pointers. The second argument is | ||||||||||||
an integer or vector of integers. | ||||||||||||
an integer or vector of integers with the same bit width as the index type | ||||||||||||
size of the first argument. | ||||||||||||
|
||||||||||||
Overview: | ||||||||||||
"""""""""" | ||||||||||||
|
@@ -26965,10 +26966,20 @@ to facilitate alias analysis and underlying-object detection. | |||||||||||
Semantics: | ||||||||||||
"""""""""" | ||||||||||||
|
||||||||||||
The result of ``ptrmask(ptr, mask)`` is equivalent to | ||||||||||||
``getelementptr ptr, (ptrtoint(ptr) & mask) - ptrtoint(ptr)``. Both the returned | ||||||||||||
pointer(s) and the first argument are based on the same underlying object (for more | ||||||||||||
information on the *based on* terminology see | ||||||||||||
The result of ``ptrmask(%ptr, %mask)`` is equivalent to the following expansion, | ||||||||||||
where ``iPtrIdx`` is the index type size of the pointer:: | ||||||||||||
arichardson marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
||||||||||||
%intptr = ptrtoint ptr %ptr to iPtrIdx ; this may truncate | ||||||||||||
%masked = and iPtrIdx %intptr, %mask | ||||||||||||
%diff = sub iPtrIdx %masked, %intptr | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this expansion works if the result of the sub is positive, does it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But %diff will always be negative right? %masked must be less than %intptr since it's the result of an and. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean the case where the subtraction overflows so the sign bit of %diff is 0. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you maybe have an example of what could go wrong here? I don't get it. The sub here gets cancelled out by the add the GEP does, I don't think overflow is relevant. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, it works specifically because everything is using iPtrIdx arithmetic, and therefore (in two's complement) does not matter whether things are positive or negative, it's just modular arithmetic There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking of an example like this, with 16-bit pointers and 8-bit indexes:
Have I misunderstood how getelementptr works? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. getelementptr only works on the index bits of the pointer. So the result would be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK but I don't see that documented in the semantics: https://llvm.org/docs/LangRef.html#id234 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please update the documentation of the semantics of getelementptr? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done as part of #70015. |
||||||||||||
%result = getelementptr i8, ptr %ptr, iPtrIdx %diff | ||||||||||||
|
||||||||||||
Considering this as an operation on the integer representation of the pointer, | ||||||||||||
if the pointer index type size is smaller than the pointer type size, this | ||||||||||||
implies that the mask is extended with 1 bits to the pointer type size. | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Maybe something like this addresses @jrtc27's comment that non-index bits are not touched at all for CHERI? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something like that does indeed sound more appropriate for pointers that aren't just plain integers (though technically our capabilities do still report as being integral, since non-integral pointers are overly-restrictive in their semantics (they imply that ptrtoint gives an unstable value, but ours are as stable as any normal integral pointer)). |
||||||||||||
|
||||||||||||
Both the returned pointer(s) and the first argument are based on the same | ||||||||||||
underlying object (for more information on the *based on* terminology see | ||||||||||||
:ref:`the pointer aliasing rules <pointeraliasing>`). If the bitwidth of the | ||||||||||||
mask argument does not match the pointer size of the target, the mask is | ||||||||||||
zero-extended or truncated accordingly. | ||||||||||||
|
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.
Is this actually true (both before and after)? I would hope that ptrmask does not have the address-exposed semantics that ptrtoint does?
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.
I've added a sentence to clarify that ptrmask only captures via the return value.