[CIR] Handle negative offsets in pointer constants#193624
Open
andykaylor wants to merge 1 commit intollvm:mainfrom
Open
[CIR] Handle negative offsets in pointer constants#193624andykaylor wants to merge 1 commit intollvm:mainfrom
andykaylor wants to merge 1 commit intollvm:mainfrom
Conversation
When a negative offset was used as an index into a global array as part of a global pointer initialization, CIR was hitting an unreachable marker while trying to construct a GlobalView attribute to describe the pointer initialization. Although this sort of negative offset is UB, Clang allows it, so we want to produce the same results via CIR. Assisted-by: Cursor / claude-4.7-opus-high
Member
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Andy Kaylor (andykaylor) ChangesWhen a negative offset was used as an index into a global array as part of a global pointer initialization, CIR was hitting an unreachable marker while trying to construct a GlobalView attribute to describe the pointer initialization. Although this sort of negative offset is UB, Clang allows it, so we want to produce the same results via CIR. Assisted-by: Cursor / claude-4.7-opus-high Full diff: https://github.com/llvm/llvm-project/pull/193624.diff 2 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
index 0cf35812babe7..c58b5041cd9cd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
@@ -91,12 +91,19 @@ void CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset(
if (!offset)
return;
+ // Compute floor-division and a non-negative remainder. A negative flat
+ // offset (e.g. from a pointer one element before the start of an array)
+ // must translate to a negative array index with a non-negative remainder
+ // so that the recursive call can descend into the element type without
+ // a negative offset flowing into the record case below.
auto getIndexAndNewOffset =
[](int64_t offset, int64_t eltSize) -> std::pair<int64_t, int64_t> {
int64_t divRet = offset / eltSize;
- if (divRet < 0)
- divRet -= 1; // make sure offset is positive
- int64_t modRet = offset - (divRet * eltSize);
+ int64_t modRet = offset % eltSize;
+ if (modRet < 0) {
+ divRet -= 1;
+ modRet += eltSize;
+ }
return {divRet, modRet};
};
diff --git a/clang/test/CIR/CodeGen/global-ptr-init-negative-offset.c b/clang/test/CIR/CodeGen/global-ptr-init-negative-offset.c
new file mode 100644
index 0000000000000..751aed20fbea4
--- /dev/null
+++ b/clang/test/CIR/CodeGen/global-ptr-init-negative-offset.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -fclangir -emit-cir -o %t.cir %s
+// RUN: FileCheck -check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -fclangir -emit-llvm -o %t-cir.ll %s
+// RUN: FileCheck -check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o %t.ll %s
+// RUN: FileCheck -check-prefix=LLVM --input-file=%t.ll %s
+
+// Constant initializers that point to an element before the start of an
+// array produce a negative flat offset (e.g. flex-generated scanner tables
+// that do `yytop = &yywork[-1]`). Although forming such a pointer is UB per
+// the C standard, Clang accepts it as a constant expression.
+
+struct Entry {
+ int verify, advance;
+};
+
+extern struct Entry arr[];
+
+struct Entry *before = &arr[-1];
+int *before_field = &arr[-1].advance;
+
+// CIR: cir.global external @before = #cir.global_view<@arr, [-1 : i32]> : !cir.ptr<!rec_Entry>
+// CIR: cir.global external @before_field = #cir.global_view<@arr, [-1 : i32, 1 : i32]> : !cir.ptr<!s32i>
+
+// LLVM: @before = global ptr getelementptr (i8, ptr @arr, i64 -8)
+// LLVM: @before_field = global ptr getelementptr (i8, ptr @arr, i64 -4)
|
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
When a negative offset was used as an index into a global array as part of a global pointer initialization, CIR was hitting an unreachable marker while trying to construct a GlobalView attribute to describe the pointer initialization. Although this sort of negative offset is UB, Clang allows it, so we want to produce the same results via CIR.
Assisted-by: Cursor / claude-4.7-opus-high