================
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir
-clangir-enable-call-conv-lowering -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: FileCheck --check-prefix=CIRGLOBAL --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir
-clangir-enable-call-conv-lowering -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefixes=LLVM,LLVM-CIR --input-file=%t-cir.ll %s
+// RUN: FileCheck --check-prefix=DECL --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefixes=LLVM,LLVM-OGCG --input-file=%t.ll %s
+// RUN: FileCheck --check-prefix=DECL --input-file=%t.ll %s
+
+// Module-level items, which the two backends order differently against the
+// function definitions, so DECL has no label blocks to be constrained by.
+// DECL-DAG: declare void @make_big(ptr dead_on_unwind writable
sret(%struct.Big) align 8, i32 noundef)
+// DECL-DAG: declare i64 @make_pair(i32 noundef)
+// DECL-DAG: @g_big = global ptr @make_big, align 8
+// DECL-DAG: @g_arr = global [1 x ptr] [ptr @make_big], align 8
+// DECL-DAG: @g_rec = global %struct.HolderS { ptr @make_big }, align 8
+
+typedef struct { long a, b, c, d; } Big;
+typedef struct { int x, y; } Pair2;
+
+Big make_big(int);
+Pair2 make_pair(int);
+
+typedef Big (*BigFP)(int);
+typedef Pair2 (*PairFP)(int);
+
+// Global initializers hold a GlobalViewAttr, not a cir.get_global.
+BigFP g_big = make_big;
+BigFP g_arr[1] = { make_big };
+struct HolderS { BigFP p; };
+struct HolderS g_rec = { make_big };
+
+// CIRGLOBAL-DAG: cir.global external @g_big = #cir.global_view<@make_big> :
!cir.ptr<!cir.func<(!s32i) -> !rec_Big>>
+// CIRGLOBAL-DAG: cir.global external @g_arr =
#cir.const_array<[#cir.global_view<@make_big> : !cir.ptr<!cir.func<(!s32i) ->
!rec_Big>>]>
+// CIRGLOBAL-DAG: cir.global external @g_rec =
#cir.const_record<{#cir.global_view<@make_big> : !cir.ptr<!cir.func<(!s32i) ->
!rec_Big>>}>
+
+// A 32-byte return becomes an sret parameter.
+BigFP get_big(void) { return make_big; }
+
+// CIR-LABEL: cir.func{{.*}} @get_big() -> !cir.ptr<!cir.func<(!s32i) ->
!rec_Big>>
+// CIR: %[[G:[0-9]+]] = cir.get_global @make_big :
!cir.ptr<!cir.func<(!cir.ptr<!rec_Big>, !s32i)>>
+// CIR-NEXT: %[[C:[0-9]+]] = cir.cast bitcast %[[G]] :
!cir.ptr<!cir.func<(!cir.ptr<!rec_Big>, !s32i)>> -> !cir.ptr<!cir.func<(!s32i)
-> !rec_Big>>
+// CIR-NEXT: cir.store %[[C]], %{{[0-9]+}} :
+
+// LLVM-LABEL: define dso_local ptr @get_big()
+// LLVM-CIR: store ptr @make_big, ptr %[[SLOT:[a-zA-Z0-9._]+]], align 8
+// LLVM-CIR: %[[FP:[a-zA-Z0-9._]+]] = load ptr, ptr %[[SLOT]], align 8
+// LLVM-CIR: ret ptr %[[FP]]
+// LLVM-OGCG: ret ptr @make_big{{$}}
+
+// An 8-byte return is coerced into a register, changing the return type.
+PairFP get_pair(void) { return make_pair; }
+
+// CIR-LABEL: cir.func{{.*}} @get_pair() -> !cir.ptr<!cir.func<(!s32i) ->
!rec_Pair2>>
+// CIR: %[[G:[0-9]+]] = cir.get_global @make_pair :
!cir.ptr<!cir.func<(!s32i) -> !u64i>>
+// CIR-NEXT: %[[C:[0-9]+]] = cir.cast bitcast %[[G]] :
!cir.ptr<!cir.func<(!s32i) -> !u64i>> -> !cir.ptr<!cir.func<(!s32i) ->
!rec_Pair2>>
+
+// LLVM-LABEL: define dso_local ptr @get_pair()
+// LLVM-CIR: store ptr @make_pair, ptr %{{[a-zA-Z0-9._]+}}, align 8
+// LLVM-OGCG: ret ptr @make_pair{{$}}
+
+// The address of a definition, whose body the sret rewrite also rewires.
+Big make_big_def(int n) { Big b = {n, n, n, n}; return b; }
+BigFP get_def(void) { return make_big_def; }
+
+// CIR-LABEL: cir.func{{.*}} @make_big_def(%arg0: !cir.ptr<!rec_Big>
{{{.*}}llvm.sret = !rec_Big{{.*}}, %arg1: !s32i {llvm.noundef}
+// CIR-LABEL: cir.func{{.*}} @get_def() -> !cir.ptr<!cir.func<(!s32i) ->
!rec_Big>>
+// CIR: %[[G:[0-9]+]] = cir.get_global @make_big_def :
!cir.ptr<!cir.func<(!cir.ptr<!rec_Big>, !s32i)>>
+// CIR-NEXT: %[[C:[0-9]+]] = cir.cast bitcast %[[G]] :
!cir.ptr<!cir.func<(!cir.ptr<!rec_Big>, !s32i)>> -> !cir.ptr<!cir.func<(!s32i)
-> !rec_Big>>
+
+// LLVM-LABEL: define dso_local void @make_big_def(ptr dead_on_unwind noalias
writable sret(%struct.Big) align 8 %{{.+}}, i32 noundef %{{.+}})
+// LLVM-LABEL: define dso_local ptr @get_def()
+// LLVM-CIR: store ptr @make_big_def, ptr %{{[a-zA-Z0-9._]+}}, align 8
+// LLVM-OGCG: ret ptr @make_big_def{{$}}
+
+// Calling through the address reaches the callee at its rewritten signature.
+Big call_local(int n) {
+ BigFP f = make_big;
+ return f(n);
+}
+
+// CIR-LABEL: cir.func{{.*}} @call_local(%arg0: !cir.ptr<!rec_Big>
{{{.*}}llvm.sret = !rec_Big{{.*}}, %arg1: !s32i {llvm.noundef}
+// CIR: %[[G:[0-9]+]] = cir.get_global @make_big :
!cir.ptr<!cir.func<(!cir.ptr<!rec_Big>, !s32i)>>
+// CIR-NEXT: %[[C:[0-9]+]] = cir.cast bitcast %[[G]] :
!cir.ptr<!cir.func<(!cir.ptr<!rec_Big>, !s32i)>> -> !cir.ptr<!cir.func<(!s32i)
-> !rec_Big>>
----------------
adams381 wrote:
@andykaylor This is effectively the same objection that you had above. As we
discussed in the sync meeting this morning this PR is starting us on the
direction we want to be going. I have planned ~3-4 future PRs that do exactly
what you describe.
https://github.com/llvm/llvm-project/pull/214082
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits