llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Erich Keane (erichkeane)

<details>
<summary>Changes</summary>

As a GNU extension, clang supports math on void* and function pointers in C 
mode only. From a CIR perspective, it makes sense to leave these types in the 
IR, since it might be useful to do analysis.

During lowering, we already properly lower these to a size-1 element, so there 
is no changes that need to happen besides letting this get through CIR 
generation.  This patch does that, plus adds some tests.

---
Full diff: https://github.com/llvm/llvm-project/pull/184254.diff


2 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (-10) 
- (added) clang/test/CIR/CodeGen/gnu-ptr-math.c (+156) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 03c8369753f35..411f973118252 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -676,11 +676,6 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
         // VLA types don't have constant size.
         cgf.cgm.errorNYI(e->getSourceRange(), "Pointer arithmetic on VLA");
         return {};
-      } else if (type->isFunctionType()) {
-        // Arithmetic on function pointers (!) is just +-1.
-        cgf.cgm.errorNYI(e->getSourceRange(),
-                         "Pointer arithmetic on function pointer");
-        return {};
       } else {
         // For everything else, we can just do a simple increment.
         mlir::Location loc = cgf.getLoc(e->getSourceRange());
@@ -1812,11 +1807,6 @@ static mlir::Value emitPointerArithmetic(CIRGenFunction 
&cgf,
     return nullptr;
   }
 
-  if (elementType->isVoidType() || elementType->isFunctionType()) {
-    cgf.cgm.errorNYI("void* or function pointer arithmetic");
-    return nullptr;
-  }
-
   assert(!cir::MissingFeatures::sanitizers());
   return cir::PtrStrideOp::create(cgf.getBuilder(),
                                   cgf.getLoc(op.e->getExprLoc()),
diff --git a/clang/test/CIR/CodeGen/gnu-ptr-math.c 
b/clang/test/CIR/CodeGen/gnu-ptr-math.c
new file mode 100644
index 0000000000000..e5b811a1d42fd
--- /dev/null
+++ b/clang/test/CIR/CodeGen/gnu-ptr-math.c
@@ -0,0 +1,156 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir 
--mlir-print-ir-before=cir-lowering-prepare %s -o %t.cir 2> %t-before.cir
+// RUN: FileCheck %s --input-file=%t-before.cir --check-prefixes=CIR
+// RUN: FileCheck %s --input-file=%t.cir --check-prefixes=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
- | FileCheck %s --check-prefixes=LLVM,LLVM_CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | 
FileCheck %s --check-prefixes=LLVM,LLVM_OG
+
+typedef void *vptr;
+typedef int(*fptr)(int, double);
+
+vptr vptr_add(vptr p) {
+  // CIR-LABEL: vptr_add
+  // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, 
["p", init]
+  // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, 
["__retval"]
+  // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+  // CIR: %[[OFFSET:.*]] = cir.const #cir.int<3> : !s32i
+  // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]]
+  // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]]
+
+  // LLVM-LABEL: vptr_add
+  // LLVM: %[[ARG:.*]] = alloca ptr
+  // LLVM_CIR: %[[RET:.*]] = alloca ptr
+  // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]]
+  // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], i64 3
+  // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]]
+  // LLVM_OG: ret ptr %[[STRIDE]]
+  return p + 3;
+}
+
+vptr vptr_sub(vptr p) {
+  // CIR-LABEL: vptr_sub
+  // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, 
["p", init]
+  // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, 
["__retval"]
+  // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+  // CIR: %[[OFFSET:.*]] = cir.const #cir.int<-2> : !s32i
+  // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]]
+  // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]]
+
+  // LLVM-LABEL: vptr_sub
+  // LLVM: %[[ARG:.*]] = alloca ptr
+  // LLVM_CIR: %[[RET:.*]] = alloca ptr
+  // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]]
+  // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], i64 -2
+  // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]]
+  // LLVM_OG: ret ptr %[[STRIDE]]
+  return p - 2;
+}
+
+vptr vptr_inc(vptr p) {
+  // CIR-LABEL: vptr_inc
+  // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, 
["p", init]
+  // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, 
["__retval"]
+  // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+  // CIR: %[[OFFSET:.*]] = cir.const #cir.int<1> : !s32i
+  // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]]
+  // CIR: cir.store {{.*}}%[[STRIDE]], %[[ARG]]
+
+  // LLVM-LABEL: vptr_inc
+  // LLVM: %[[ARG:.*]] = alloca ptr
+  // LLVM_CIR: %[[RET:.*]] = alloca ptr
+  // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]]
+  // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], {{.*}} 1
+  // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]]
+  // LLVM_OG: store ptr %[[STRIDE]], ptr %[[ARG]]
+  return p ++;
+}
+vptr vptr_dec(vptr p) {
+  // CIR-LABEL: vptr_dec
+  // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, 
["p", init]
+  // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, 
["__retval"]
+  // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+  // CIR: %[[OFFSET:.*]] = cir.const #cir.int<-1> : !s32i
+  // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]]
+  // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]]
+
+  // LLVM-LABEL: vptr_dec
+  // LLVM: %[[ARG:.*]] = alloca ptr
+  // LLVM_CIR: %[[RET:.*]] = alloca ptr
+  // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]]
+  // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], {{.*}} 
-1
+  // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]]
+  // LLVM_OG: ret ptr %[[STRIDE]]
+  return --p;
+}
+
+fptr fptr_add(fptr p) {
+  // CIR-LABEL: fptr_add
+  // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> 
!s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["p", 
init]
+  // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> 
!s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, 
["__retval"]
+  // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : 
!cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, 
!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>
+  // CIR: %[[OFFSET:.*]] = cir.const #cir.int<3> : !s32i
+  // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]]
+  // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]]
+
+  // LLVM-LABEL: fptr_add
+  // LLVM: %[[ARG:.*]] = alloca ptr
+  // LLVM-CIR: %[[RET:.*]] = alloca ptr
+  // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]]
+  // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], i64 3
+  // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]]
+  // LLVM_OG: ret ptr %[[STRIDE]]
+  return p + 3;
+}
+
+fptr fptr_sub(fptr p) {
+  // CIR-LABEL: fptr_sub
+  // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> 
!s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["p", 
init]
+  // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> 
!s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, 
["__retval"]
+  // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : 
!cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, 
!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>
+  // CIR: %[[OFFSET:.*]] = cir.const #cir.int<-2> : !s32i
+  // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]]
+  // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]]
+
+  // LLVM-LABEL: fptr_sub
+  // LLVM: %[[ARG:.*]] = alloca ptr
+  // LLVM_CIR: %[[RET:.*]] = alloca ptr
+  // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]]
+  // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], i64 -2
+  // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]]
+  // LLVM_OG: ret ptr %[[STRIDE]]
+  return p - 2;
+}
+
+fptr fptr_inc(fptr p) {
+  // CIR-LABEL: fptr_inc
+  // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> 
!s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["p", 
init]
+  // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> 
!s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, 
["__retval"]
+  // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : 
!cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, 
!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>
+  // CIR: %[[OFFSET:.*]] = cir.const #cir.int<1> : !s32i
+  // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]]
+  // CIR: cir.store {{.*}}%[[STRIDE]], %[[ARG]]
+
+  // LLVM-LABEL: fptr_inc
+  // LLVM: %[[ARG:.*]] = alloca ptr
+  // LLVM_CIR: %[[RET:.*]] = alloca ptr
+  // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], {{.*}} 1
+  // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]]
+  // LLVM_OG: store ptr %[[STRIDE]], ptr %[[ARG]]
+  return p ++;
+}
+fptr fptr_dec(fptr p) {
+  // CIR-LABEL: fptr_dec
+  // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> 
!s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["p", 
init]
+  // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> 
!s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, 
["__retval"]
+  // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : 
!cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, 
!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>
+  // CIR: %[[OFFSET:.*]] = cir.const #cir.int<-1> : !s32i
+  // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]]
+  // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]]
+
+  // LLVM-LABEL: fptr_dec
+  // LLVM: %[[ARG:.*]] = alloca ptr
+  // LLVM_CIR: %[[RET:.*]] = alloca ptr
+  // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], {{.*}} 
-1
+  // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]]
+  // LLVM_OG: ret ptr %[[STRIDE]]
+  return --p;
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/184254
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to