brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.8 KiB · e7d199b Raw
200 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir2// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s3// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll4// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s5// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll6// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s7 8// We declare anonymous record types to represent lambdas. Rather than trying to9// to match the declarations, we establish variables for these when they are used.10 11int g3() {12  auto* fn = +[](int const& i) -> int { return i; };13  auto task = fn(3);14  return task;15}16 17// The order of these functions is different in OGCG.18 19// OGCG: define dso_local noundef i32 @_Z2g3v()20// OGCG:   %[[FN_PTR:.*]] = alloca ptr21// OGCG:   %[[REF_TMP:.*]] = alloca %[[REC_LAM_G3:.*]]22// OGCG:   %[[TASK:.*]] = alloca i3223// OGCG:   %[[REF_TMP1:.*]] = alloca i3224// OGCG:   %[[CALL:.*]] = call {{.*}} ptr @"_ZZ2g3vENK3$_0cvPFiRKiEEv"(ptr {{.*}} %[[REF_TMP]])25// OGCG:   store ptr %[[CALL]], ptr %[[FN_PTR]]26// OGCG:   %[[FN:.*]] = load ptr, ptr %[[FN_PTR]]27// OGCG:   store i32 3, ptr %[[REF_TMP1]]28// OGCG:   %[[CALL2:.*]] = call {{.*}} i32 %[[FN]](ptr {{.*}} %[[REF_TMP1]])29// OGCG:   store i32 %[[CALL2]], ptr %[[TASK]]30// OGCG:   %[[RESULT:.*]] = load i32, ptr %[[TASK]]31// OGCG:   ret i32 %[[RESULT]]32 33// OGCG: define internal noundef ptr @"_ZZ2g3vENK3$_0cvPFiRKiEEv"(ptr {{.*}} %[[THIS_ARG:.*]])34// OGCG:   %[[THIS_ADDR:.*]] = alloca ptr35// OGCG:   store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]36// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]37// OGCG:   ret ptr @"_ZZ2g3vEN3$_08__invokeERKi"38 39// lambda operator()40// CIR: cir.func lambda internal private dso_local @_ZZ2g3vENK3$_0clERKi(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_G3:.*]]> {{.*}}, %[[REF_I_ARG:.*]]: !cir.ptr<!s32i> {{.*}})41// CIR:   %[[THIS_ALLOCA:.*]] = cir.alloca !cir.ptr<![[REC_LAM_G3]]>, !cir.ptr<!cir.ptr<![[REC_LAM_G3]]>>, ["this", init]42// CIR:   %[[REF_I_ALLOCA:.*]] = cir.alloca {{.*}} ["i", init, const]43// CIR:   %[[RETVAL:.*]] = cir.alloca {{.*}} ["__retval"]44// CIR:   cir.store %[[THIS_ARG]], %[[THIS_ALLOCA]]45// CIR:   cir.store %[[REF_I_ARG]], %[[REF_I_ALLOCA]]46// CIR:   %[[THIS:.*]] = cir.load %[[THIS_ALLOCA]]47// CIR:   %[[REF_I:.*]] = cir.load %[[REF_I_ALLOCA]]48// CIR:   %[[I:.*]] = cir.load{{.*}} %[[REF_I]]49// CIR:   cir.store %[[I]], %[[RETVAL]]50// CIR:   %[[RET:.*]] = cir.load %[[RETVAL]]51// CIR:   cir.return %[[RET]]52 53// LLVM: define internal i32 @"_ZZ2g3vENK3$_0clERKi"(ptr %[[THIS_ARG:.*]], ptr %[[REF_I_ARG:.*]]){{.*}} {54// LLVM:   %[[THIS_ALLOCA:.*]] = alloca ptr55// LLVM:   %[[REF_I_ALLOCA:.*]] = alloca ptr56// LLVM:   %[[RETVAL:.*]] = alloca i3257// LLVM:   store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]58// LLVM:   store ptr %[[REF_I_ARG]], ptr %[[REF_I_ALLOCA]]59// LLVM:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]60// LLVM:   %[[REF_I:.*]] = load ptr, ptr %[[REF_I_ALLOCA]]61// LLVM:   %[[I:.*]] = load i32, ptr %[[REF_I]]62// LLVM:   store i32 %[[I]], ptr %[[RETVAL]]63// LLVM:   %[[RET:.*]] = load i32, ptr %[[RETVAL]]64// LLVM:   ret i32 %[[RET]]65 66// In OGCG, the _ZZ2g3vENK3$_0clERKi function is emitted after _ZZ2g3vEN3$_08__invokeERKi, see below.67 68// lambda invoker69// CIR: cir.func internal private dso_local @_ZZ2g3vEN3$_08__invokeERKi(%[[REF_I_ARG:.*]]: !cir.ptr<!s32i> {{.*}}) -> !s32i{{.*}} {70// CIR:   %[[REF_I_ALLOCA:.*]] = cir.alloca {{.*}} ["i", init, const]71// CIR:   %[[RETVAL:.*]] = cir.alloca {{.*}} ["__retval"]72// CIR:   %[[LAM_ALLOCA:.*]] = cir.alloca ![[REC_LAM_G3]], !cir.ptr<![[REC_LAM_G3]]>, ["unused.capture"]73// CIR:   cir.store %[[REF_I_ARG]], %[[REF_I_ALLOCA]]74// CIR:   %[[REF_I:.*]] = cir.load{{.*}} %[[REF_I_ALLOCA]]75// CIR:   %[[LAM_RESULT:.*]] = cir.call @_ZZ2g3vENK3$_0clERKi(%2, %3) : (!cir.ptr<![[REC_LAM_G3]]>, !cir.ptr<!s32i>) -> !s32i76// CIR:   cir.store{{.*}} %[[LAM_RESULT]], %[[RETVAL]]77// CIR:   %[[RET:.*]] = cir.load %[[RETVAL]]78// CIR:   cir.return %[[RET]]79 80// LLVM: define internal i32 @"_ZZ2g3vEN3$_08__invokeERKi"(ptr %[[REF_I_ARG:.*]]){{.*}} {81// LLVM:   %[[REF_I_ALLOCA:.*]] = alloca ptr82// LLVM:   %[[RETVAL:.*]] = alloca i3283// LLVM:   %[[LAM_ALLOCA:.*]] = alloca %[[REC_LAM_G3:.*]],84// LLVM:   store ptr %[[REF_I_ARG]], ptr %[[REF_I_ALLOCA]]85// LLVM:   %[[REF_I:.*]] = load ptr, ptr %[[REF_I_ALLOCA]]86// LLVM:   %[[LAM_RESULT:.*]] = call i32 @"_ZZ2g3vENK3$_0clERKi"(ptr %[[LAM_ALLOCA]], ptr %[[REF_I]])87// LLVM:   store i32 %[[LAM_RESULT]], ptr %[[RETVAL]]88// LLVM:   %[[RET:.*]] = load i32, ptr %[[RETVAL]]89// LLVM:   ret i32 %[[RET]]90 91// In OGCG, the _ZZ2g3vEN3$_08__invokeERKi function is emitted after _ZN1A3barEv, see below.92 93// lambda operator int (*)(int const&)()94// CIR:   cir.func internal private dso_local @_ZZ2g3vENK3$_0cvPFiRKiEEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_G3]]> {{.*}}) -> !cir.ptr<!cir.func<(!cir.ptr<!s32i>) -> !s32i>>{{.*}} {95// CIR:   %[[THIS_ALLOCA:.*]] = cir.alloca !cir.ptr<![[REC_LAM_G3]]>, !cir.ptr<!cir.ptr<![[REC_LAM_G3]]>>, ["this", init]96// CIR:   %[[RETVAL:.*]] = cir.alloca !cir.ptr<!cir.func<(!cir.ptr<!s32i>) -> !s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!s32i>) -> !s32i>>>, ["__retval"]97// CIR:   cir.store %[[THIS_ARG]], %[[THIS_ALLOCA]]98// CIR:   %[[THIS:.*]] = cir.load %[[THIS_ALLOCA]]99// CIR:   %[[INVOKER:.*]] = cir.get_global @_ZZ2g3vEN3$_08__invokeERKi : !cir.ptr<!cir.func<(!cir.ptr<!s32i>) -> !s32i>>100// CIR:   cir.store %[[INVOKER]], %[[RETVAL]]101// CIR:   %[[RET:.*]] = cir.load %[[RETVAL]]102// CIR:   cir.return %[[RET]]103 104// LLVM: define internal ptr @"_ZZ2g3vENK3$_0cvPFiRKiEEv"(ptr %[[THIS_ARG:.*]]){{.*}} {105// LLVM:  %[[THIS_ALLOCA:.*]] = alloca ptr106// LLVM:  %[[RETVAL:.*]] = alloca ptr107// LLVM:  store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]108// LLVM:  %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]109// LLVM:  store ptr @"_ZZ2g3vEN3$_08__invokeERKi", ptr %[[RETVAL]]110// LLVM:  %[[RET:.*]] = load ptr, ptr %[[RETVAL]]111// LLVM:  ret ptr %[[RET]]112 113// In OGCG, the _ZZ2g3vENK3$_0cvPFiRKiEEv function is emitted just after the _Z2g3v function, see above.114 115// CIR: cir.func{{.*}} @_Z2g3v() -> !s32i{{.*}} {116// CIR:   %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]117// CIR:   %[[FN_ADDR:.*]] = cir.alloca !cir.ptr<!cir.func<(!cir.ptr<!s32i>) -> !s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!s32i>) -> !s32i>>>, ["fn", init]118// CIR:   %[[TASK:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["task", init]119 120// 1. Use `operator int (*)(int const&)()` to retrieve the fnptr to `__invoke()`.121// CIR:     %[[SCOPE_RET:.*]] = cir.scope {122// CIR:       %[[LAM_ALLOCA:.*]] = cir.alloca ![[REC_LAM_G3]], !cir.ptr<![[REC_LAM_G3]]>, ["ref.tmp0"]123// CIR:       %[[OPERATOR_RESULT:.*]] = cir.call @_ZZ2g3vENK3$_0cvPFiRKiEEv(%[[LAM_ALLOCA]]){{.*}}124// CIR:       %[[PLUS:.*]] = cir.unary(plus, %[[OPERATOR_RESULT]])125// CIR:       cir.yield %[[PLUS]]126// CIR:     }127 128// 2. Load ptr to `__invoke()`.129// CIR:     cir.store{{.*}} %[[SCOPE_RET]], %[[FN_ADDR]]130// CIR:     %[[SCOPE_RET2:.*]] = cir.scope {131// CIR:       %[[REF_TMP1:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp1", init]132// CIR:       %[[FN:.*]] = cir.load{{.*}} %[[FN_ADDR]]133// CIR:       %[[THREE:.*]] = cir.const #cir.int<3> : !s32i134// CIR:       cir.store{{.*}} %[[THREE]], %[[REF_TMP1]]135 136// 3. Call `__invoke()`, which effectively executes `operator()`.137// CIR:       %[[RESULT:.*]] = cir.call %[[FN]](%[[REF_TMP1]])138// CIR:       cir.yield %[[RESULT]]139// CIR:     }140 141// CIR:     cir.store{{.*}} %[[SCOPE_RET2]], %[[TASK]]142// CIR:     %[[TASK_RET:.*]] = cir.load{{.*}} %[[TASK]]143// CIR:     cir.store{{.*}} %[[TASK_RET]], %[[RETVAL]]144// CIR:     %[[RET:.*]] = cir.load{{.*}} %[[RETVAL]]145// CIR:     cir.return %[[RET]]146// CIR:   }147 148// LLVM: define dso_local i32 @_Z2g3v(){{.*}} {149// LLVM:   %[[LAM_ALLOCA:.*]] = alloca %[[REC_LAM_G3]]150// LLVM:   %[[REF_TMP1:.*]] = alloca i32151// LLVM:   %[[RETVAL:.*]] = alloca i32152// LLVM:   %[[FN_PTR:.*]] = alloca ptr153// LLVM:   %[[TASK:.*]] = alloca i32154// LLVM:   br label %[[SCOPE_BB0:.*]]155 156// LLVM: [[SCOPE_BB0]]:157// LLVM:   %[[OPERATOR_RESULT:.*]] = call ptr @"_ZZ2g3vENK3$_0cvPFiRKiEEv"(ptr %[[LAM_ALLOCA]])158// LLVM:   br label %[[SCOPE_BB1:.*]]159 160// LLVM: [[SCOPE_BB1]]:161// LLVM:   %[[TMP0:.*]] = phi ptr [ %[[OPERATOR_RESULT]], %[[SCOPE_BB0]] ]162// LLVM:   store ptr %[[TMP0]], ptr %[[FN_PTR]]163// LLVM:   br label %[[SCOPE_BB2:.*]]164 165// LLVM: [[SCOPE_BB2]]:166// LLVM:   %[[FN:.*]] = load ptr, ptr %[[FN_PTR]]167// LLVM:   store i32 3, ptr %[[REF_TMP1]]168// LLVM:   %[[RESULT:.*]] = call i32 %[[FN]](ptr %[[REF_TMP1]])169// LLVM:   br label %[[RET_BB:.*]]170 171// LLVM: [[RET_BB]]:172// LLVM:   %[[TMP1:.*]] = phi i32 [ %[[RESULT]], %[[SCOPE_BB2]] ]173// LLVM:   store i32 %[[TMP1]], ptr %[[TASK]]174// LLVM:   %[[TMP2:.*]] = load i32, ptr %[[TASK]]175// LLVM:   store i32 %[[TMP2]], ptr %[[RETVAL]]176// LLVM:   %[[RET:.*]] = load i32, ptr %[[RETVAL]]177// LLVM:   ret i32 %[[RET]]178 179// The definition for _Z2g3v in OGCG is first among the functions for the g3 test, see above.180 181// The functions below are emitted later in OGCG, see above for the corresponding LLVM checks.182 183// OGCG: define internal noundef i32 @"_ZZ2g3vEN3$_08__invokeERKi"(ptr {{.*}} %[[I_ARG:.*]])184// OGCG:   %[[I_ADDR:.*]] = alloca ptr185// OGCG:   %[[UNUSED_CAPTURE:.*]] = alloca %[[REC_LAM_G3:.*]]186// OGCG:   store ptr %[[I_ARG]], ptr %[[I_ADDR]]187// OGCG:   %[[I_PTR:.*]] = load ptr, ptr %[[I_ADDR]]188// OGCG:   %[[CALL:.*]] = call {{.*}} i32 @"_ZZ2g3vENK3$_0clERKi"(ptr {{.*}} %[[UNUSED_CAPTURE]], ptr {{.*}} %[[I_PTR]])189// OGCG:   ret i32 %[[CALL]]190 191// OGCG: define internal noundef i32 @"_ZZ2g3vENK3$_0clERKi"(ptr {{.*}} %[[THIS_ARG:.*]], ptr {{.*}} %[[I_ARG:.*]])192// OGCG:   %[[THIS_ADDR:.*]] = alloca ptr193// OGCG:   %[[I_ADDR:.*]] = alloca ptr194// OGCG:   store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]195// OGCG:   store ptr %[[I_ARG]], ptr %[[I_ADDR]]196// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]197// OGCG:   %[[I_PTR:.*]] = load ptr, ptr %[[I_ADDR]]198// OGCG:   %[[I:.*]] = load i32, ptr %[[I_PTR]]199// OGCG:   ret i32 %[[I]]200