-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[Clang][CodeGen] Respect -fwrapv-pointer when emitting struct GEPs #134269
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
Conversation
@llvm/pr-subscribers-clang Author: Yingwei Zheng (dtcxzyw) ChangesThis patch turns off inbounds/nuw flags for member accesses when Closes #132449. It is required by #130734. Full diff: https://github.com/llvm/llvm-project/pull/134269.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 3d3a111f0514a..d32591ed896d0 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4922,6 +4922,9 @@ static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base,
unsigned idx =
CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
+ if (CGF.getLangOpts().PointerOverflowDefined)
+ return CGF.Builder.CreateConstGEP2_32(base, 0, idx, field->getName());
+
return CGF.Builder.CreateStructGEP(base, idx, field->getName());
}
@@ -4979,9 +4982,13 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
if (!UseVolatile) {
if (!IsInPreservedAIRegion &&
(!getDebugInfo() || !rec->hasAttr<BPFPreserveAccessIndexAttr>())) {
- if (Idx != 0)
+ if (Idx != 0) {
// For structs, we GEP to the field that the record layout suggests.
- Addr = Builder.CreateStructGEP(Addr, Idx, field->getName());
+ if (getLangOpts().PointerOverflowDefined)
+ Addr = Builder.CreateConstGEP2_32(Addr, 0, Idx, field->getName());
+ else
+ Addr = Builder.CreateStructGEP(Addr, Idx, field->getName());
+ }
} else {
llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateRecordType(
getContext().getRecordType(rec), rec->getLocation());
diff --git a/clang/test/CodeGen/pointer-overflow.c b/clang/test/CodeGen/pointer-overflow.c
index 9c7821b841980..70e3c855bff90 100644
--- a/clang/test/CodeGen/pointer-overflow.c
+++ b/clang/test/CodeGen/pointer-overflow.c
@@ -10,3 +10,24 @@ void test(void) {
// DEFAULT: getelementptr inbounds nuw i32, ptr
// FWRAPV-POINTER: getelementptr i32, ptr
}
+
+struct S {
+ int a;
+ int b;
+ int c: 10;
+ int d: 10;
+};
+
+int test_struct(struct S* s) {
+ // -fwrapv-pointer should turn off inbounds nuw for struct GEP's
+ return s->b;
+ // DEFAULT: getelementptr inbounds nuw %struct.S, ptr
+ // FWRAPV-POINTER: getelementptr %struct.S, ptr
+}
+
+int test_struct_bitfield(struct S* s) {
+ // -fwrapv-pointer should turn off inbounds nuw for struct GEP's
+ return s->d;
+ // DEFAULT: getelementptr inbounds nuw %struct.S, ptr
+ // FWRAPV-POINTER: getelementptr %struct.S, ptr
+}
|
@llvm/pr-subscribers-clang-codegen Author: Yingwei Zheng (dtcxzyw) ChangesThis patch turns off inbounds/nuw flags for member accesses when Closes #132449. It is required by #130734. Full diff: https://github.com/llvm/llvm-project/pull/134269.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 3d3a111f0514a..d32591ed896d0 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4922,6 +4922,9 @@ static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base,
unsigned idx =
CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
+ if (CGF.getLangOpts().PointerOverflowDefined)
+ return CGF.Builder.CreateConstGEP2_32(base, 0, idx, field->getName());
+
return CGF.Builder.CreateStructGEP(base, idx, field->getName());
}
@@ -4979,9 +4982,13 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
if (!UseVolatile) {
if (!IsInPreservedAIRegion &&
(!getDebugInfo() || !rec->hasAttr<BPFPreserveAccessIndexAttr>())) {
- if (Idx != 0)
+ if (Idx != 0) {
// For structs, we GEP to the field that the record layout suggests.
- Addr = Builder.CreateStructGEP(Addr, Idx, field->getName());
+ if (getLangOpts().PointerOverflowDefined)
+ Addr = Builder.CreateConstGEP2_32(Addr, 0, Idx, field->getName());
+ else
+ Addr = Builder.CreateStructGEP(Addr, Idx, field->getName());
+ }
} else {
llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateRecordType(
getContext().getRecordType(rec), rec->getLocation());
diff --git a/clang/test/CodeGen/pointer-overflow.c b/clang/test/CodeGen/pointer-overflow.c
index 9c7821b841980..70e3c855bff90 100644
--- a/clang/test/CodeGen/pointer-overflow.c
+++ b/clang/test/CodeGen/pointer-overflow.c
@@ -10,3 +10,24 @@ void test(void) {
// DEFAULT: getelementptr inbounds nuw i32, ptr
// FWRAPV-POINTER: getelementptr i32, ptr
}
+
+struct S {
+ int a;
+ int b;
+ int c: 10;
+ int d: 10;
+};
+
+int test_struct(struct S* s) {
+ // -fwrapv-pointer should turn off inbounds nuw for struct GEP's
+ return s->b;
+ // DEFAULT: getelementptr inbounds nuw %struct.S, ptr
+ // FWRAPV-POINTER: getelementptr %struct.S, ptr
+}
+
+int test_struct_bitfield(struct S* s) {
+ // -fwrapv-pointer should turn off inbounds nuw for struct GEP's
+ return s->d;
+ // DEFAULT: getelementptr inbounds nuw %struct.S, ptr
+ // FWRAPV-POINTER: getelementptr %struct.S, ptr
+}
|
Looks good to me, but please allow some time for other reviewers to weigh in. |
What's the distinguishing factor here? Do you consider it "safe" to mark inbounds if the pointer is immediately dereferenced? Or does the pointer have to refer to a known successful allocation? Or something else? |
Other calls to |
Usually we'd want to also insert |
A struct GEP is unlikely to overflow. But a null check should be useful. |
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 makes sense to me but this is not my area.
struct S { | ||
int a; | ||
int b; | ||
int c: 10; |
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 am curious why did you add bit-fields in specifically to this test? Are they particularly different wrt other types of fields like arrays, pointers, member pointers etc that we would expect them to break?
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.
Bitfields are handled by a different code path:
llvm-project/clang/lib/CodeGen/CGExpr.cpp
Line 4977 in 2c1bdd4
Addr = Builder.CreateStructGEP(Addr, Idx, field->getName()); |
@efriedma-quic Any more comments? |
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.
LGTM
…lvm#134269) This patch turns off inbounds/nuw flags for member accesses when `-fwrapv-pointer` is set. Closes llvm#132449. It is required by llvm#130734.
…lvm#134269) This patch turns off inbounds/nuw flags for member accesses when `-fwrapv-pointer` is set. Closes llvm#132449. It is required by llvm#130734.
This patch turns off inbounds/nuw flags for member accesses when
-fwrapv-pointer
is set.Note: There are many calls to
CGBuilderTy::CreateStructGEP
, and most of them are safe. So I think it is probably overkill to handle this inCreateStructGEP
.Closes #132449.
It is required by #130734.