-
Notifications
You must be signed in to change notification settings - Fork 13.7k
[TBAA] Emit distinct TBAA tags for pointers with different depths,types. #76612
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
Changes from all commits
1939aea
0a8a503
a69317d
16437fc
8e1da97
e6ef5e7
9952f79
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 |
---|---|---|
|
@@ -185,10 +185,56 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { | |
return getChar(); | ||
|
||
// Handle pointers and references. | ||
// TODO: Implement C++'s type "similarity" and consider dis-"similar" | ||
// pointers distinct. | ||
if (Ty->isPointerType() || Ty->isReferenceType()) | ||
return createScalarTypeNode("any pointer", getChar(), Size); | ||
// | ||
// C has a very strict rule for pointer aliasing. C23 6.7.6.1p2: | ||
// For two pointer types to be compatible, both shall be identically | ||
// qualified and both shall be pointers to compatible types. | ||
// | ||
// This rule is impractically strict; we want to at least ignore CVR | ||
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 agree with this for the default behavior, but I think we should still allow opting into the strict C conformance behavior so that users can sanitize the code for portability to stricter compilers (also, it may allow for different optimization impacts that users might care about... maybe). This can be follow-up work though. 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. Sounds good! |
||
// qualifiers. Distinguishing by CVR qualifiers would make it UB to | ||
// e.g. cast a `char **` to `const char * const *` and dereference it, | ||
// which is too common and useful to invalidate. C++'s similar types | ||
// rule permits qualifier differences in these nested positions; in fact, | ||
// C++ even allows that cast as an implicit conversion. | ||
// | ||
// Other qualifiers could theoretically be distinguished, especially if | ||
// they involve a significant representation difference. We don't | ||
// currently do so, however. | ||
// | ||
// Computing the pointee type string recursively is implicitly more | ||
// forgiving than the standards require. Effectively, we are turning | ||
// the question "are these types compatible/similar" into "are | ||
// accesses to these types allowed to alias". In both C and C++, | ||
// the latter question has special carve-outs for signedness | ||
// mismatches that only apply at the top level. As a result, we are | ||
// allowing e.g. `int *` l-values to access `unsigned *` objects. | ||
if (Ty->isPointerType() || Ty->isReferenceType()) { | ||
llvm::MDNode *AnyPtr = createScalarTypeNode("any pointer", getChar(), Size); | ||
if (!CodeGenOpts.PointerTBAA) | ||
return AnyPtr; | ||
// Compute the depth of the pointer and generate a tag of the form "p<depth> | ||
// <base type tag>". | ||
unsigned PtrDepth = 0; | ||
do { | ||
PtrDepth++; | ||
Ty = Ty->getPointeeType().getTypePtr(); | ||
} while (Ty->isPointerType()); | ||
// TODO: Implement C++'s type "similarity" and consider dis-"similar" | ||
// pointers distinct for non-builtin types. | ||
if (isa<BuiltinType>(Ty)) { | ||
llvm::MDNode *ScalarMD = getTypeInfoHelper(Ty); | ||
StringRef Name = | ||
cast<llvm::MDString>( | ||
ScalarMD->getOperand(CodeGenOpts.NewStructPathTBAA ? 2 : 0)) | ||
->getString(); | ||
SmallString<256> OutName("p"); | ||
OutName += std::to_string(PtrDepth); | ||
OutName += " "; | ||
OutName += Name; | ||
return createScalarTypeNode(OutName, AnyPtr, Size); | ||
} | ||
return AnyPtr; | ||
} | ||
|
||
// Accesses to arrays are accesses to objects of their element types. | ||
if (CodeGenOpts.NewStructPathTBAA && Ty->isArrayType()) | ||
|
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.
Probably worth putting standard citations here:
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.
Added, thank you very much!