-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[Clang][CodeGen] Add workaround for old glibc __PTR_ALIGN
macro
#137851
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-codegen Author: Yingwei Zheng (dtcxzyw) ChangesCloses #137833. Full diff: https://github.com/llvm/llvm-project/pull/137851.diff 4 Files Affected:
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index bba7d1e805f3f..e9e22321e2634 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4820,6 +4820,9 @@ bool CodeGenFunction::isUnderlyingBasePointerConstantNull(const Expr *E) {
const Expr *UnderlyingBaseExpr = E->IgnoreParens();
while (auto *BaseMemberExpr = dyn_cast<MemberExpr>(UnderlyingBaseExpr))
UnderlyingBaseExpr = BaseMemberExpr->getBase()->IgnoreParens();
+ if (auto *Select = dyn_cast<ConditionalOperator>(UnderlyingBaseExpr))
+ return isUnderlyingBasePointerConstantNull(Select->getTrueExpr()) ||
+ isUnderlyingBasePointerConstantNull(Select->getFalseExpr());
return getContext().isSentinelNullExpr(UnderlyingBaseExpr);
}
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 8dbbcdaef25d8..d214d2af52563 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4238,7 +4238,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
else
elemTy = CGF.ConvertTypeForMem(elementType);
- if (CGF.getLangOpts().PointerOverflowDefined)
+ if (CGF.getLangOpts().PointerOverflowDefined ||
+ CGF.isUnderlyingBasePointerConstantNull(pointerOperand))
return CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr");
return CGF.EmitCheckedInBoundsGEP(
diff --git a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c
index 63b6db2c2adeb..c5ae3f8bcc368 100644
--- a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c
+++ b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c
@@ -431,6 +431,18 @@ char *void_ptr(void *base, unsigned long offset) {
return base + offset;
}
+int *constant_null_add(long offset) {
+ // CHECK: define{{.*}} ptr @constant_null_add(i64 noundef %[[OFFSET:.*]])
+ // CHECK-NEXT: [[ENTRY:.*]]:
+ // CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8
+ // CHECK-NEXT: store i64 %[[OFFSET]], ptr %[[OFFSET_ADDR]], align 8
+ // CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, ptr %[[OFFSET_ADDR]], align 8
+ // CHECK-NEXT: %[[ADD_PTR:.*]] = getelementptr i32, ptr null, i64 %[[OFFSET_RELOADED]]
+ // CHECK-NEXT: ret ptr %[[ADD_PTR]]
+#line 1800
+ return (int *)0 + offset;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/clang/test/CodeGen/glibc_ptr_align.c b/clang/test/CodeGen/glibc_ptr_align.c
new file mode 100644
index 0000000000000..14968a8326509
--- /dev/null
+++ b/clang/test/CodeGen/glibc_ptr_align.c
@@ -0,0 +1,22 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -O3 -o - -emit-llvm %s | FileCheck %s
+
+// Make sure that we do not set inbounds flag if the base pointer may be a constant null.
+
+// CHECK-LABEL: define dso_local noalias ptr @glibc_ptr_align(
+// CHECK-SAME: ptr noundef readnone captures(none) [[BASE:%.*]], ptr noundef [[POINTER:%.*]], i64 noundef [[ALIGN_MASK:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[POINTER]] to i64
+// CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[ALIGN_MASK]], [[SUB_PTR_LHS_CAST]]
+// CHECK-NEXT: [[NOT:%.*]] = xor i64 [[ALIGN_MASK]], -1
+// CHECK-NEXT: [[AND:%.*]] = and i64 [[ADD]], [[NOT]]
+// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr i8, ptr null, i64 [[AND]]
+// CHECK-NEXT: ret ptr [[ADD_PTR]]
+//
+char *glibc_ptr_align(char *base, char *pointer, long align_mask) {
+ return (sizeof(long int) < sizeof(void *) ? (base) : (char *)0) +
+ (((pointer) -
+ (sizeof(long int) < sizeof(void *) ? (base) : (char *)0) +
+ (align_mask)) &
+ ~(align_mask));
+}
|
@llvm/pr-subscribers-clang Author: Yingwei Zheng (dtcxzyw) ChangesCloses #137833. Full diff: https://github.com/llvm/llvm-project/pull/137851.diff 4 Files Affected:
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index bba7d1e805f3f..e9e22321e2634 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4820,6 +4820,9 @@ bool CodeGenFunction::isUnderlyingBasePointerConstantNull(const Expr *E) {
const Expr *UnderlyingBaseExpr = E->IgnoreParens();
while (auto *BaseMemberExpr = dyn_cast<MemberExpr>(UnderlyingBaseExpr))
UnderlyingBaseExpr = BaseMemberExpr->getBase()->IgnoreParens();
+ if (auto *Select = dyn_cast<ConditionalOperator>(UnderlyingBaseExpr))
+ return isUnderlyingBasePointerConstantNull(Select->getTrueExpr()) ||
+ isUnderlyingBasePointerConstantNull(Select->getFalseExpr());
return getContext().isSentinelNullExpr(UnderlyingBaseExpr);
}
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 8dbbcdaef25d8..d214d2af52563 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4238,7 +4238,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
else
elemTy = CGF.ConvertTypeForMem(elementType);
- if (CGF.getLangOpts().PointerOverflowDefined)
+ if (CGF.getLangOpts().PointerOverflowDefined ||
+ CGF.isUnderlyingBasePointerConstantNull(pointerOperand))
return CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr");
return CGF.EmitCheckedInBoundsGEP(
diff --git a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c
index 63b6db2c2adeb..c5ae3f8bcc368 100644
--- a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c
+++ b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c
@@ -431,6 +431,18 @@ char *void_ptr(void *base, unsigned long offset) {
return base + offset;
}
+int *constant_null_add(long offset) {
+ // CHECK: define{{.*}} ptr @constant_null_add(i64 noundef %[[OFFSET:.*]])
+ // CHECK-NEXT: [[ENTRY:.*]]:
+ // CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8
+ // CHECK-NEXT: store i64 %[[OFFSET]], ptr %[[OFFSET_ADDR]], align 8
+ // CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, ptr %[[OFFSET_ADDR]], align 8
+ // CHECK-NEXT: %[[ADD_PTR:.*]] = getelementptr i32, ptr null, i64 %[[OFFSET_RELOADED]]
+ // CHECK-NEXT: ret ptr %[[ADD_PTR]]
+#line 1800
+ return (int *)0 + offset;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/clang/test/CodeGen/glibc_ptr_align.c b/clang/test/CodeGen/glibc_ptr_align.c
new file mode 100644
index 0000000000000..14968a8326509
--- /dev/null
+++ b/clang/test/CodeGen/glibc_ptr_align.c
@@ -0,0 +1,22 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -O3 -o - -emit-llvm %s | FileCheck %s
+
+// Make sure that we do not set inbounds flag if the base pointer may be a constant null.
+
+// CHECK-LABEL: define dso_local noalias ptr @glibc_ptr_align(
+// CHECK-SAME: ptr noundef readnone captures(none) [[BASE:%.*]], ptr noundef [[POINTER:%.*]], i64 noundef [[ALIGN_MASK:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[POINTER]] to i64
+// CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[ALIGN_MASK]], [[SUB_PTR_LHS_CAST]]
+// CHECK-NEXT: [[NOT:%.*]] = xor i64 [[ALIGN_MASK]], -1
+// CHECK-NEXT: [[AND:%.*]] = and i64 [[ADD]], [[NOT]]
+// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr i8, ptr null, i64 [[AND]]
+// CHECK-NEXT: ret ptr [[ADD_PTR]]
+//
+char *glibc_ptr_align(char *base, char *pointer, long align_mask) {
+ return (sizeof(long int) < sizeof(void *) ? (base) : (char *)0) +
+ (((pointer) -
+ (sizeof(long int) < sizeof(void *) ? (base) : (char *)0) +
+ (align_mask)) &
+ ~(align_mask));
+}
|
This fixes an issue I was seeing caused by #130742 that caused GNU m4 and make builds to segfault, which I assume was caused by #137833. I don't understand the code here well enough to give an actual review, but it'd be great to see this merged as m4/make builds generating bad binaries is causing a lot of other issues. |
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
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/19726 Here is the relevant piece of the build log for the reference
|
Closes #137833.
This patch is stacked on #137849.