Skip to content

Commit 8a592d6

Browse files
PragmaTwicelanza
authored andcommitted
[CIR][LowerToLLVM] Support pointer arithmetic for function types (llvm#594)
Same as void pointers `void *`, we treat function pointer arithmetic as `GEP i8`, according to the original behavior of clang ([godbolt](https://godbolt.org/z/EMdvfdTe7)).
1 parent 832e0c8 commit 8a592d6

File tree

2 files changed

+40
-10
lines changed

2 files changed

+40
-10
lines changed

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -485,10 +485,12 @@ class CIRPtrStrideOpLowering
485485
auto *tc = getTypeConverter();
486486
const auto resultTy = tc->convertType(ptrStrideOp.getType());
487487
auto elementTy = tc->convertType(ptrStrideOp.getElementTy());
488-
auto ctx = elementTy.getContext();
488+
auto *ctx = elementTy.getContext();
489489

490-
// void doesn't really have a layout to use in GEPs, make it i8 instead.
491-
if (elementTy.isa<mlir::LLVM::LLVMVoidType>())
490+
// void and function types doesn't really have a layout to use in GEPs,
491+
// make it i8 instead.
492+
if (elementTy.isa<mlir::LLVM::LLVMVoidType>() ||
493+
elementTy.isa<mlir::LLVM::LLVMFunctionType>())
492494
elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
493495
mlir::IntegerType::Signless);
494496

clang/test/CIR/CodeGen/pointer-arith-ext.c

+35-7
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,41 @@ void *f4(void *a, int b) { return a - b; }
4848
// Similar to f4, just make sure it does not crash.
4949
void *f4_1(void *a, int b) { return (a -= b); }
5050

51+
FP f5(FP a, int b) { return a + b; }
52+
// CIR-LABEL: f5
53+
// CIR: %[[PTR:.*]] = cir.load {{.*}} : !cir.ptr<!cir.ptr<!cir.func<!void ()>>>, !cir.ptr<!cir.func<!void ()>>
54+
// CIR: %[[STRIDE:.*]] = cir.load {{.*}} : !cir.ptr<!s32i>, !s32i
55+
// CIR: cir.ptr_stride(%[[PTR]] : !cir.ptr<!cir.func<!void ()>>, %[[STRIDE]] : !s32i)
56+
57+
// LLVM-LABEL: f5
58+
// LLVM: %[[PTR:.*]] = load ptr, ptr {{.*}}, align 8
59+
// LLVM: %[[TOEXT:.*]] = load i32, ptr {{.*}}, align 4
60+
// LLVM: %[[STRIDE:.*]] = sext i32 %[[TOEXT]] to i64
61+
// LLVM: getelementptr i8, ptr %[[PTR]], i64 %[[STRIDE]]
62+
63+
// These test the same paths above, just make sure it does not crash.
64+
FP f5_1(FP a, int b) { return (a += b); }
65+
FP f6(int a, FP b) { return a + b; }
66+
FP f6_1(int a, FP b) { return (a += b); }
67+
68+
FP f7(FP a, int b) { return a - b; }
69+
// CIR-LABEL: f7
70+
// CIR: %[[PTR:.*]] = cir.load {{.*}} : !cir.ptr<!cir.ptr<!cir.func<!void ()>>>, !cir.ptr<!cir.func<!void ()>>
71+
// CIR: %[[STRIDE:.*]] = cir.load {{.*}} : !cir.ptr<!s32i>, !s32i
72+
// CIR: %[[SUB:.*]] = cir.unary(minus, %[[STRIDE]]) : !s32i, !s32i
73+
// CIR: cir.ptr_stride(%[[PTR]] : !cir.ptr<!cir.func<!void ()>>, %[[SUB]] : !s32i)
74+
75+
// LLVM-LABEL: f7
76+
// LLVM: %[[PTR:.*]] = load ptr, ptr {{.*}}, align 8
77+
// LLVM: %[[TOEXT:.*]] = load i32, ptr {{.*}}, align 4
78+
// LLVM: %[[STRIDE:.*]] = sext i32 %[[TOEXT]] to i64
79+
// LLVM: %[[SUB:.*]] = sub i64 0, %[[STRIDE]]
80+
// LLVM: getelementptr i8, ptr %[[PTR]], i64 %[[SUB]]
81+
82+
// Similar to f7, just make sure it does not crash.
83+
FP f7_1(FP a, int b) { return (a -= b); }
84+
5185
// FIXME: add support for the remaining ones.
52-
// FP f5(FP a, int b) { return a + b; }
53-
// FP f5_1(FP a, int b) { return (a += b); }
54-
// FP f6(int a, FP b) { return a + b; }
55-
// FP f6_1(int a, FP b) { return (a += b); }
56-
// FP f7(FP a, int b) { return a - b; }
57-
// FP f7_1(FP a, int b) { return (a -= b); }
5886
// void f8(void *a, int b) { return *(a + b); }
5987
// void f8_1(void *a, int b) { return a[b]; }
6088

@@ -69,4 +97,4 @@ unsigned char *p(unsigned int x) {
6997
// CIR: cir.ptr_stride({{.*}} : !cir.ptr<!u8i>, %[[SUB]] : !u32i), !cir.ptr<!u8i>
7098

7199
// LLVM-LABEL: @p
72-
// LLVM: getelementptr i8, ptr {{.*}}
100+
// LLVM: getelementptr i8, ptr {{.*}}

0 commit comments

Comments
 (0)