From 031bf709f2eec69f923abe8d14ecec2dd09c6087 Mon Sep 17 00:00:00 2001 From: gitoleg Date: Wed, 13 Dec 2023 18:28:09 +0300 Subject: [PATCH] [CIR][Lowering] Fix function ptr field lowering in a global struct (#353) This PR fixes a global vars lowering with a funciton ptr field. Previously, the next code caused fail in the `foo` lowering: ``` static void myfun(int a) {} static struct { void (*func)(int flag); } const Handlers[] = { {myfun}, {myfun}, {myfun} }; void foo(int i, int flag) { Handlers[i].func(flag); } ``` --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 6 +++- clang/test/CIR/Lowering/globals.cir | 34 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index fd77f49fd294..182fb65d78e7 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -229,7 +229,11 @@ mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, } else if (auto llvmFun = dyn_cast(sourceSymbol)) { sourceType = llvmFun.getFunctionType(); symName = llvmFun.getSymName(); - } else { + } else if (auto fun = dyn_cast(sourceSymbol)) { + sourceType = converter->convertType(fun.getFunctionType()); + symName = fun.getSymName(); + } + else { llvm_unreachable("Unexpected GlobalOp type"); } diff --git a/clang/test/CIR/Lowering/globals.cir b/clang/test/CIR/Lowering/globals.cir index e4d3ee2fe740..052c2045752b 100644 --- a/clang/test/CIR/Lowering/globals.cir +++ b/clang/test/CIR/Lowering/globals.cir @@ -2,7 +2,9 @@ // RUN: FileCheck --input-file=%t.cir %s -check-prefix=MLIR // RUN: cir-translate %s -cir-to-llvmir -o %t.ll // RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM +// XFAIL: * +!void = !cir.void !s16i = !cir.int !s32i = !cir.int !s64i = !cir.int @@ -14,6 +16,7 @@ !ty_22Bar22 = !cir.struct !ty_22StringStruct22 = !cir.struct, !cir.array, !cir.array} #cir.record.decl.ast> !ty_22StringStructPtr22 = !cir.struct} #cir.record.decl.ast> +!ty_22anon2E122 = !cir.struct)>>} #cir.record.decl.ast> module { cir.global external @a = #cir.int<3> : !s32i @@ -146,4 +149,33 @@ module { // MLIR: } cir.global common @comm = #cir.int<0> : !s32i // MLIR: llvm.mlir.global common @comm(0 : i32) {addr_space = 0 : i32} : i32 -} + + cir.global "private" internal @Handlers = #cir.const_array<[#cir.const_struct<{#cir.global_view<@myfun> : !cir.ptr>}> : !ty_22anon2E122]> : !cir.array + cir.func internal private @myfun(%arg0: !s32i) { + %0 = cir.alloca !s32i, cir.ptr , ["a", init] {alignment = 4 : i64} + cir.store %arg0, %0 : !s32i, cir.ptr + cir.return + } + cir.func @foo(%arg0: !s32i, %arg1: !s32i) { + %0 = cir.alloca !s32i, cir.ptr , ["i", init] {alignment = 4 : i64} + %1 = cir.alloca !s32i, cir.ptr , ["flag", init] {alignment = 4 : i64} + cir.store %arg0, %0 : !s32i, cir.ptr + cir.store %arg1, %1 : !s32i, cir.ptr + %2 = cir.get_global @Handlers : cir.ptr > + %3 = cir.load %0 : cir.ptr , !s32i + %4 = cir.cast(array_to_ptrdecay, %2 : !cir.ptr>), !cir.ptr + %5 = cir.ptr_stride(%4 : !cir.ptr, %3 : !s32i), !cir.ptr + %6 = cir.get_member %5[0] {name = "func"} : !cir.ptr -> !cir.ptr>> + %7 = cir.load %6 : cir.ptr >>, !cir.ptr> + %8 = cir.load %1 : cir.ptr , !s32i + cir.call %7(%8) : (!cir.ptr>, !s32i) -> () + cir.return + } + //MLIR: %[[RES4:.*]] = llvm.mlir.addressof @Handlers : !llvm.ptr + //MLIR: %[[RES5:.*]] = llvm.load {{.*}} : !llvm.ptr -> i32 + //MLIR: %[[RES6:.*]] = llvm.getelementptr %[[RES4]][0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"struct.anon.1", (ptr)> + //MLIR: %[[RES7:.*]] = llvm.getelementptr %[[RES6]][%[[RES5]]] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.anon.1", (ptr)> + //MLIR: %[[RES8:.*]] = llvm.getelementptr %[[RES7]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"struct.anon.1", (ptr)> + //MLIR: %[[RES9:.*]] = llvm.load %[[RES8]] : !llvm.ptr -> !llvm.ptr + //MLIR: llvm.call %[[RES9]]({{.*}}) : !llvm.ptr, (i32) -> () +} \ No newline at end of file