brintos

brintos / llvm-project-archived public Read only

0
0
Text · 25.1 KiB · 1d06496 Raw
514 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 11auto global_lambda = [](){};12void use_global_lambda() {13  global_lambda();14}15 16// CIR: cir.global "private" internal dso_local @global_lambda = #cir.undef : ![[REC_LAM_GLOBAL_LAMBDA:.*]] {alignment = 1 : i64}17// CIR: cir.func lambda internal private dso_local @_ZNK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]> {{.*}})18// CIR:   %[[THIS:.*]] = cir.alloca !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>, !cir.ptr<!cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>>, ["this", init]19// CIR:   cir.store %[[THIS_ARG]], %[[THIS]]20// CIR:   cir.load %[[THIS]]21//22// CIR: cir.func {{.*}} @_Z17use_global_lambdav()23// CIR:   %[[LAMBDA:.*]] = cir.get_global @global_lambda : !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>24// CIR:   cir.call @_ZNK3$_0clEv(%[[LAMBDA]]) : (!cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>) -> ()25 26// LLVM: @global_lambda = internal global %[[REC_LAM_GLOBAL_LAMBDA:.*]] undef, align 127// LLVM: define internal void @"_ZNK3$_0clEv"(ptr %[[THIS_ARG:.*]])28// LLVM:   %[[THIS_ADDR:.*]] = alloca ptr29// LLVM:   store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]30// LLVM:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]31//32// LLVM: define dso_local void @_Z17use_global_lambdav()33// LLVM:   call void @"_ZNK3$_0clEv"(ptr @global_lambda)34 35// OGCG: @global_lambda = internal global %[[REC_LAM_GLOBAL_LAMBDA:.*]] undef, align 136// OGCG: define dso_local void @_Z17use_global_lambdav()37// OGCG:   call void @"_ZNK3$_0clEv"(ptr noundef nonnull align 1 dereferenceable(1) @global_lambda)38//39// OGCG: define internal void @"_ZNK3$_0clEv"(ptr {{.*}} %[[THIS_ARG:.*]])40// OGCG:   %[[THIS_ADDR:.*]] = alloca ptr41// OGCG:   store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]42// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]43 44void fn() {45  auto a = [](){};46  a();47}48 49// CIR: cir.func lambda internal private dso_local @_ZZ2fnvENK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_FN_A:.*]]> {{.*}}) {{.*}} {50// CIR:   %[[THIS:.*]] = cir.alloca !cir.ptr<![[REC_LAM_FN_A]]>, !cir.ptr<!cir.ptr<![[REC_LAM_FN_A]]>>, ["this", init]51// CIR:   cir.store %[[THIS_ARG]], %[[THIS]]52// CIR:   cir.load %[[THIS]]53// CIR:   cir.return54 55// CIR: cir.func dso_local @_Z2fnv() {{.*}} {56// CIR:   %[[A:.*]] = cir.alloca ![[REC_LAM_FN_A]], !cir.ptr<![[REC_LAM_FN_A]]>, ["a"]57// CIR:   cir.call @_ZZ2fnvENK3$_0clEv(%[[A]])58 59// LLVM: define internal void @"_ZZ2fnvENK3$_0clEv"(ptr %[[THIS_ARG:.*]])60// LLVM:   %[[THIS_ADDR:.*]] = alloca ptr61// LLVM:   store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]62// LLVM:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]63// LLVM:   ret void64 65// FIXME: parameter attributes should be emitted66// LLVM: define {{.*}} void @_Z2fnv()67// LLVM:   [[A:%.*]] = alloca %[[REC_LAM_FN_A:.*]], i64 1, align 168// LLVM:   call void @"_ZZ2fnvENK3$_0clEv"(ptr [[A]])69// LLVM:   ret void70 71// OGCG: define {{.*}} void @_Z2fnv()72// OGCG:   %[[A:.*]] = alloca %[[REC_LAM_FN_A:.*]]73// OGCG:   call void @"_ZZ2fnvENK3$_0clEv"(ptr {{.*}} %[[A]])74// OGCG:   ret void75 76// OGCG: define internal void @"_ZZ2fnvENK3$_0clEv"(ptr {{.*}} %[[THIS_ARG:.*]])77// OGCG:   %[[THIS_ADDR:.*]] = alloca ptr78// OGCG:   store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]79// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]80// OGCG:   ret void81 82void l0() {83  int i;84  auto a = [&](){ i = i + 1; };85  a();86}87 88// CIR: cir.func lambda internal private dso_local @_ZZ2l0vENK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_L0_A:.*]]> {{.*}}) {{.*}} {89// CIR:   %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<![[REC_LAM_L0_A]]>, !cir.ptr<!cir.ptr<![[REC_LAM_L0_A]]>>, ["this", init] {alignment = 8 : i64}90// CIR:   cir.store %[[THIS_ARG]], %[[THIS_ADDR]]91// CIR:   %[[THIS:.*]] = cir.load %[[THIS_ADDR]]92// CIR:   %[[I_ADDR_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "i"}93// CIR:   %[[I_ADDR:.*]] = cir.load %[[I_ADDR_ADDR]]94// CIR:   %[[I:.*]] = cir.load align(4) %[[I_ADDR]]95// CIR:   %[[ONE:.*]] = cir.const #cir.int<1> : !s32i96// CIR:   %[[I_PLUS_ONE:.*]] = cir.binop(add, %[[I]], %[[ONE]]) nsw97// CIR:   %[[I_ADDR_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "i"}98// CIR:   %[[I_ADDR:.*]] = cir.load %[[I_ADDR_ADDR]]99// CIR:   cir.store{{.*}} %[[I_PLUS_ONE]], %[[I_ADDR]]100// CIR:   cir.return101 102// CIR: cir.func {{.*}} @_Z2l0v() {{.*}} {103// CIR:   %[[I:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i"]104// CIR:   %[[A:.*]] = cir.alloca ![[REC_LAM_L0_A]], !cir.ptr<![[REC_LAM_L0_A]]>, ["a", init]105// CIR:   %[[I_ADDR:.*]] = cir.get_member %[[A]][0] {name = "i"}106// CIR:   cir.store{{.*}} %[[I]], %[[I_ADDR]]107// CIR:   cir.call @_ZZ2l0vENK3$_0clEv(%[[A]])108// CIR:   cir.return109 110// LLVM: define internal void @"_ZZ2l0vENK3$_0clEv"(ptr %[[THIS_ARG:.*]])111// LLVM:   %[[THIS_ADDR:.*]] = alloca ptr112// LLVM:   store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]113// LLVM:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]114// LLVM:   %[[I_ADDR_ADDR:.*]] = getelementptr %[[REC_LAM_L0_A:.*]], ptr %[[THIS]], i32 0, i32 0115// LLVM:   %[[I_ADDR:.*]] = load ptr, ptr %[[I_ADDR_ADDR]]116// LLVM:   %[[I:.*]] = load i32, ptr %[[I_ADDR]]117// LLVM:   %[[ADD:.*]] = add nsw i32 %[[I]], 1118// LLVM:   %[[I_ADDR_ADDR:.*]] = getelementptr %[[REC_LAM_L0_A]], ptr %[[THIS]], i32 0, i32 0119// LLVM:   %[[I_ADDR:.*]] = load ptr, ptr %[[I_ADDR_ADDR]]120// LLVM:   store i32 %[[ADD]], ptr %[[I_ADDR]]121// LLVM:   ret void122 123// LLVM: define {{.*}} void @_Z2l0v()124// LLVM:   %[[I:.*]] = alloca i32125// LLVM:   %[[A:.*]] = alloca %[[REC_LAM_L0_A]]126// LLVM:   %[[I_ADDR:.*]] = getelementptr %[[REC_LAM_L0_A]], ptr %[[A]], i32 0, i32 0127// LLVM:   store ptr %[[I]], ptr %[[I_ADDR]]128// LLVM:   call void @"_ZZ2l0vENK3$_0clEv"(ptr %[[A]])129// LLVM:   ret void130 131// OGCG: define {{.*}} void @_Z2l0v()132// OGCG:   %[[I:.*]] = alloca i32133// OGCG:   %[[A:.*]] = alloca %[[REC_LAM_L0_A:.*]],134// OGCG:   %[[I_ADDR:.*]] = getelementptr inbounds nuw %[[REC_LAM_L0_A]], ptr %[[A]], i32 0, i32 0135// OGCG:   store ptr %[[I]], ptr %[[I_ADDR]]136// OGCG:   call void @"_ZZ2l0vENK3$_0clEv"(ptr {{.*}} %[[A]])137// OGCG:   ret void138 139// OGCG: define internal void @"_ZZ2l0vENK3$_0clEv"(ptr {{.*}} %[[THIS_ARG:.*]])140// OGCG:   %[[THIS_ADDR:.*]] = alloca ptr141// OGCG:   store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]142// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]143// OGCG:   %[[I_ADDR_ADDR:.*]] = getelementptr inbounds nuw %[[REC_LAM_L0_A]], ptr %[[THIS]], i32 0, i32 0144// OGCG:   %[[I_ADDR:.*]] = load ptr, ptr %[[I_ADDR_ADDR]]145// OGCG:   %[[I:.*]] = load i32, ptr %[[I_ADDR]]146// OGCG:   %[[ADD:.*]] = add nsw i32 %[[I]], 1147// OGCG:   %[[I_ADDR_ADDR:.*]] = getelementptr inbounds nuw %[[REC_LAM_L0_A]], ptr %[[THIS]], i32 0, i32 0148// OGCG:   %[[I_ADDR:.*]] = load ptr, ptr %[[I_ADDR_ADDR]]149// OGCG:   store i32 %[[ADD]], ptr %[[I_ADDR]]150// OGCG:   ret void151 152auto g() {153  int i = 12;154  return [&] {155    i += 100;156    return i;157  };158}159 160// CIR: cir.func dso_local @_Z1gv() -> ![[REC_LAM_G:.*]] {{.*}} {161// CIR:   %[[RETVAL:.*]] = cir.alloca ![[REC_LAM_G]], !cir.ptr<![[REC_LAM_G]]>, ["__retval"]162// CIR:   %[[I_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init]163// CIR:   %[[TWELVE:.*]] = cir.const #cir.int<12> : !s32i164// CIR:   cir.store{{.*}} %[[TWELVE]], %[[I_ADDR]] : !s32i, !cir.ptr<!s32i>165// CIR:   %[[I_ADDR_ADDR:.*]] = cir.get_member %[[RETVAL]][0] {name = "i"} : !cir.ptr<![[REC_LAM_G]]> -> !cir.ptr<!cir.ptr<!s32i>>166// CIR:   cir.store{{.*}} %[[I_ADDR]], %[[I_ADDR_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>167// CIR:   %[[RET:.*]] = cir.load{{.*}} %[[RETVAL]] : !cir.ptr<![[REC_LAM_G]]>, ![[REC_LAM_G]]168// CIR:   cir.return %[[RET]] : ![[REC_LAM_G]]169 170// Note: In this case, OGCG returns a pointer to the 'i' field of the lambda,171//       whereas CIR and LLVM return the lambda itself.172 173// LLVM: define dso_local %[[REC_LAM_G:.*]] @_Z1gv()174// LLVM:   %[[RETVAL:.*]] = alloca %[[REC_LAM_G]]175// LLVM:   %[[I:.*]] = alloca i32176// LLVM:   store i32 12, ptr %[[I]]177// LLVM:   %[[I_ADDR:.*]] = getelementptr %[[REC_LAM_G]], ptr %[[RETVAL]], i32 0, i32 0178// LLVM:   store ptr %[[I]], ptr %[[I_ADDR]]179// LLVM:   %[[RET:.*]] = load %[[REC_LAM_G]], ptr %[[RETVAL]]180// LLVM:   ret %[[REC_LAM_G]] %[[RET]]181 182// OGCG: define dso_local ptr @_Z1gv()183// OGCG:   %[[RETVAL:.*]] = alloca %[[REC_LAM_G:.*]],184// OGCG:   %[[I:.*]] = alloca i32185// OGCG:   store i32 12, ptr %[[I]]186// OGCG:   %[[I_ADDR:.*]] = getelementptr inbounds nuw %[[REC_LAM_G]], ptr %[[RETVAL]], i32 0, i32 0187// OGCG:   store ptr %[[I]], ptr %[[I_ADDR]]188// OGCG:   %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[REC_LAM_G]], ptr %[[RETVAL]], i32 0, i32 0189// OGCG:   %[[RET:.*]] = load ptr, ptr %[[COERCE_DIVE]]190// OGCG:   ret ptr %[[RET]]191 192auto g2() {193  int i = 12;194  auto lam = [&] {195    i += 100;196    return i;197  };198  return lam;199}200 201// Should be same as above because of NRVO202// CIR: cir.func dso_local @_Z2g2v() -> ![[REC_LAM_G2:.*]] {{.*}} {203// CIR:   %[[RETVAL:.*]] = cir.alloca ![[REC_LAM_G2]], !cir.ptr<![[REC_LAM_G2]]>, ["__retval", init]204// CIR:   %[[I_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init]205// CIR:   %[[TWELVE:.*]] = cir.const #cir.int<12> : !s32i206// CIR:   cir.store{{.*}} %[[TWELVE]], %[[I_ADDR]] : !s32i, !cir.ptr<!s32i>207// CIR:   %[[I_ADDR_ADDR:.*]] = cir.get_member %[[RETVAL]][0] {name = "i"} : !cir.ptr<![[REC_LAM_G2]]> -> !cir.ptr<!cir.ptr<!s32i>>208// CIR:   cir.store{{.*}} %[[I_ADDR]], %[[I_ADDR_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>209// CIR:   %[[RET:.*]] = cir.load{{.*}} %[[RETVAL]] : !cir.ptr<![[REC_LAM_G2]]>, ![[REC_LAM_G2]]210// CIR:   cir.return %[[RET]] : ![[REC_LAM_G2]]211 212// LLVM: define dso_local %[[REC_LAM_G:.*]] @_Z2g2v()213// LLVM:   %[[RETVAL:.*]] = alloca %[[REC_LAM_G]]214// LLVM:   %[[I:.*]] = alloca i32215// LLVM:   store i32 12, ptr %[[I]]216// LLVM:   %[[I_ADDR:.*]] = getelementptr %[[REC_LAM_G]], ptr %[[RETVAL]], i32 0, i32 0217// LLVM:   store ptr %[[I]], ptr %[[I_ADDR]]218// LLVM:   %[[RET:.*]] = load %[[REC_LAM_G]], ptr %[[RETVAL]]219// LLVM:   ret %[[REC_LAM_G]] %[[RET]]220 221// OGCG: define dso_local ptr @_Z2g2v()222// OGCG:   %[[RETVAL:.*]] = alloca %[[REC_LAM_G2:.*]],223// OGCG:   %[[I:.*]] = alloca i32224// OGCG:   store i32 12, ptr %[[I]]225// OGCG:   %[[I_ADDR:.*]] = getelementptr inbounds nuw %[[REC_LAM_G2]], ptr %[[RETVAL]], i32 0, i32 0226// OGCG:   store ptr %[[I]], ptr %[[I_ADDR]]227// OGCG:   %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[REC_LAM_G2]], ptr %[[RETVAL]], i32 0, i32 0228// OGCG:   %[[RET:.*]] = load ptr, ptr %[[COERCE_DIVE]]229// OGCG:   ret ptr %[[RET]]230 231int f() {232  return g2()();233}234 235// CIR:cir.func lambda internal private dso_local @_ZZ2g2vENK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_G2]]> {{.*}}) -> !s32i {{.*}} {236// CIR:   %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<![[REC_LAM_G2]]>, !cir.ptr<!cir.ptr<![[REC_LAM_G2]]>>, ["this", init]237// CIR:   %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]238// CIR:   cir.store %[[THIS_ARG]], %[[THIS_ADDR]]239// CIR:   %[[THIS:.*]] = cir.load %[[THIS_ADDR]]240// CIR:   %[[ONE_HUNDRED:.*]] = cir.const #cir.int<100> : !s32i241// CIR:   %[[I_ADDR_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "i"}242// CIR:   %[[I_ADDR:.*]] = cir.load %[[I_ADDR_ADDR]]243// CIR:   %[[I:.*]] = cir.load{{.*}} %[[I_ADDR]]244// CIR:   %[[I_PLUS_ONE_HUNDRED:.*]] = cir.binop(add, %[[I]], %[[ONE_HUNDRED]]) nsw : !s32i245// CIR:   cir.store{{.*}} %[[I_PLUS_ONE_HUNDRED]], %[[I_ADDR]] : !s32i, !cir.ptr<!s32i>246// CIR:   %[[I_ADDR_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "i"}247// CIR:   %[[I_ADDR:.*]] = cir.load %[[I_ADDR_ADDR]]248// CIR:   %[[I:.*]] = cir.load{{.*}} %[[I_ADDR]]249// CIR:   cir.store{{.*}} %[[I]], %[[RETVAL]]250// CIR:   %[[RET:.*]] = cir.load %[[RETVAL]]251// CIR:   cir.return %[[RET]]252 253// CIR: cir.func dso_local @_Z1fv() -> !s32i {{.*}} {254// CIR:   %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]255// CIR:   cir.scope {256// CIR:     %[[TMP:.*]] = cir.alloca ![[REC_LAM_G2]], !cir.ptr<![[REC_LAM_G2]]>, ["ref.tmp0"]257// CIR:     %[[G2:.*]] = cir.call @_Z2g2v() : () -> ![[REC_LAM_G2]]258// CIR:     cir.store{{.*}} %[[G2]], %[[TMP]]259// CIR:     %[[RESULT:.*]] = cir.call @_ZZ2g2vENK3$_0clEv(%[[TMP]])260// CIR:     cir.store{{.*}} %[[RESULT]], %[[RETVAL]]261// CIR:   }262// CIR:   %[[RET:.*]] = cir.load{{.*}} %[[RETVAL]]263// CIR:   cir.return %[[RET]]264 265// LLVM: define internal i32 @"_ZZ2g2vENK3$_0clEv"(ptr %[[THIS_ARG:.*]])266// LLVM:   %[[THIS_ALLOCA:.*]] = alloca ptr267// LLVM:   %[[I_ALLOCA:.*]] = alloca i32268// LLVM:   store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]269// LLVM:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]270// LLVM:   %[[I_ADDR_ADDR:.*]] = getelementptr %[[REC_LAM_G2:.*]], ptr %[[THIS]], i32 0, i32 0271// LLVM:   %[[I_ADDR:.*]] = load ptr, ptr %[[I_ADDR_ADDR]]272// LLVM:   %[[I:.*]] = load i32, ptr %[[I_ADDR]]273// LLVM:   %[[ADD:.*]] = add nsw i32 %[[I]], 100274// LLVM:   store i32 %[[ADD]], ptr %[[I_ADDR]]275// LLVM:   %[[I_ADDR_ADDR:.*]] = getelementptr %[[REC_LAM_G2]], ptr %[[THIS]], i32 0, i32 0276// LLVM:   %[[I_ADDR:.*]] = load ptr, ptr %[[I_ADDR_ADDR]]277// LLVM:   %[[I:.*]] = load i32, ptr %[[I_ADDR]]278// LLVM:   store i32 %[[I]], ptr %[[I_ALLOCA]]279// LLVM:   %[[RET:.*]] = load i32, ptr %[[I_ALLOCA]]280// LLVM:   ret i32 %[[RET]]281 282// LLVM: define {{.*}} i32 @_Z1fv()283// LLVM:   %[[TMP:.*]] = alloca %[[REC_LAM_G2]]284// LLVM:   %[[RETVAL:.*]] = alloca i32285// LLVM:   br label %[[SCOPE_BB:.*]]286// LLVM: [[SCOPE_BB]]:287// LLVM:   %[[G2:.*]] = call %[[REC_LAM_G2]] @_Z2g2v()288// LLVM:   store %[[REC_LAM_G2]] %[[G2]], ptr %[[TMP]]289// LLVM:   %[[RESULT:.*]] = call i32 @"_ZZ2g2vENK3$_0clEv"(ptr %[[TMP]])290// LLVM:   store i32 %[[RESULT]], ptr %[[RETVAL]]291// LLVM:   br label %[[RET_BB:.*]]292// LLVM: [[RET_BB]]:293// LLVM:   %[[RET:.*]] = load i32, ptr %[[RETVAL]]294// LLVM:   ret i32 %[[RET]]295 296// The order of these functions is reversed in OGCG.297 298// OGCG: define {{.*}} i32 @_Z1fv()299// OGCG:   %[[TMP:.*]] = alloca %[[REC_LAM_G2]]300// OGCG:   %[[RESULT:.*]] = call ptr @_Z2g2v()301// OGCG:   %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[REC_LAM_G2]], ptr %[[TMP]], i32 0, i32 0302// OGCG:   store ptr %[[RESULT]], ptr %[[COERCE_DIVE]]303// OGCG:   %[[RET:.*]] = call {{.*}} i32 @"_ZZ2g2vENK3$_0clEv"(ptr {{.*}} %[[TMP]])304// OGCG:   ret i32 %[[RET]]305 306// OGCG: define internal noundef i32 @"_ZZ2g2vENK3$_0clEv"(ptr {{.*}} %[[THIS_ARG:.*]])307// OGCG:   %[[THIS_ALLOCA:.*]] = alloca ptr308// OGCG:   store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]309// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]310// OGCG:   %[[I_ADDR_ADDR:.*]] = getelementptr inbounds nuw %[[REC_LAM_G2]], ptr %[[THIS]], i32 0, i32 0311// OGCG:   %[[I_ADDR:.*]] = load ptr, ptr %[[I_ADDR_ADDR]]312// OGCG:   %[[I:.*]] = load i32, ptr %[[I_ADDR]]313// OGCG:   %[[ADD:.*]] = add nsw i32 %[[I]], 100314// OGCG:   store i32 %[[ADD]], ptr %[[I_ADDR]]315// OGCG:   %[[I_ADDR_ADDR:.*]] = getelementptr inbounds nuw %[[REC_LAM_G2]], ptr %[[THIS]], i32 0, i32 0316// OGCG:   %[[I_ADDR:.*]] = load ptr, ptr %[[I_ADDR_ADDR]]317// OGCG:   %[[I:.*]] = load i32, ptr %[[I_ADDR]]318// OGCG:   ret i32 %[[I]]319 320struct A {321  int a = 111;322  int foo() { return [*this] { return a; }(); }323  int bar() { return [this] { return a; }(); }324};325 326// This function gets emitted before the lambdas in OGCG.327 328// OGCG: define {{.*}} i32 @_Z17test_lambda_this1v329// OGCG:   %[[A_THIS:.*]] = alloca %struct.A330// OGCG:   call void @_ZN1AC1Ev(ptr {{.*}} %[[A_THIS]])331// OGCG:   call noundef i32 @_ZN1A3fooEv(ptr {{.*}} %[[A_THIS]])332// OGCG:   call noundef i32 @_ZN1A3barEv(ptr {{.*}} %[[A_THIS]])333 334// lambda operator() in foo()335// CIR: cir.func lambda comdat linkonce_odr @_ZZN1A3fooEvENKUlvE_clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_A:.*]]> {{.*}}) {{.*}} {336// CIR:   %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<![[REC_LAM_A]]>, !cir.ptr<!cir.ptr<![[REC_LAM_A]]>>, ["this", init]337// CIR:   %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]338// CIR:   cir.store{{.*}} %[[THIS_ARG]], %[[THIS_ADDR]]339// CIR:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]340// CIR:   %[[STRUCT_A:.*]] = cir.get_member %[[THIS]][0] {name = "this"}341// CIR:   %[[A_A_ADDR:.*]] = cir.get_member %[[STRUCT_A]][0] {name = "a"}342// CIR:   %[[A_A:.*]] = cir.load{{.*}} %[[A_A_ADDR]]343// CIR:   cir.store{{.*}} %[[A_A]], %[[RETVAL]]344// CIR:   %[[RET:.*]] = cir.load{{.*}} %[[RETVAL]]345// CIR:   cir.return %[[RET]]346 347// LLVM: define linkonce_odr i32 @_ZZN1A3fooEvENKUlvE_clEv(ptr %[[THIS_ARG:.*]])348// LLVM:   %[[THIS_ALLOCA:.*]]  = alloca ptr349// LLVM:   %[[RETVAL:.*]] = alloca i32350// LLVM:   store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]351// LLVM:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]352// LLVM:   %[[PTR_A:.*]] = getelementptr %[[REC_LAM_A:.*]], ptr %[[THIS]], i32 0, i32 0353// LLVM:   %[[A_A_ADDR:.*]] = getelementptr %struct.A, ptr %[[PTR_A]], i32 0, i32 0354// LLVM:   %[[A_A:.*]] = load i32, ptr %[[A_A_ADDR]]355// LLVM:   store i32 %[[A_A]], ptr %[[RETVAL]]356// LLVM:   %[[RET:.*]] = load i32, ptr %[[RETVAL]]357// LLVM:   ret i32 %[[RET]]358 359// The function above is defined after _ZN1A3barEv in OGCG, see below.360 361// A::foo()362// CIR: cir.func {{.*}} @_ZN1A3fooEv(%[[THIS_ARG:.*]]: !cir.ptr<!rec_A> {{.*}}) -> !s32i {{.*}} {363// CIR:   %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_A>, !cir.ptr<!cir.ptr<!rec_A>>, ["this", init]364// CIR:   %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]365// CIR:   cir.store %[[THIS_ARG]], %[[THIS_ADDR]]366// CIR:   %[[THIS]] = cir.load deref %[[THIS_ADDR]] : !cir.ptr<!cir.ptr<!rec_A>>, !cir.ptr<!rec_A>367// CIR:   cir.scope {368// CIR:     %[[LAM_ADDR:.*]] = cir.alloca ![[REC_LAM_A]], !cir.ptr<![[REC_LAM_A]]>, ["ref.tmp0"]369// CIR:     %[[STRUCT_A:.*]] = cir.get_member %[[LAM_ADDR]][0] {name = "this"} : !cir.ptr<![[REC_LAM_A]]> -> !cir.ptr<!rec_A>370// CIR:     cir.call @_ZN1AC1ERKS_(%[[STRUCT_A]], %[[THIS]]){{.*}} : (!cir.ptr<!rec_A>, !cir.ptr<!rec_A>){{.*}} -> ()371// CIR:     %[[LAM_RET:.*]] = cir.call @_ZZN1A3fooEvENKUlvE_clEv(%[[LAM_ADDR]])372// CIR:     cir.store{{.*}} %[[LAM_RET]], %[[RETVAL]]373// CIR:   }374// CIR:   %[[RET:.*]] = cir.load{{.*}} %[[RETVAL]]375// CIR:   cir.return %[[RET]]376 377// LLVM: define linkonce_odr i32 @_ZN1A3fooEv(ptr %[[THIS_ARG:.*]])378// LLVM:   %[[LAM_ALLOCA:.*]] =  alloca %[[REC_LAM_A]]379// LLVM:   %[[THIS_ALLOCA:.*]] = alloca ptr380// LLVM:   %[[RETVAL:.*]] = alloca i32381// LLVM:   store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]382// LLVM:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]383// LLVM:   br label %[[SCOPE_BB:.*]]384// LLVM: [[SCOPE_BB]]:385// LLVM:   %[[STRUCT_A:.*]] = getelementptr %[[REC_LAM_A]], ptr %[[LAM_ALLOCA]], i32 0, i32 0386// LLVM:   call void @_ZN1AC1ERKS_(ptr %[[STRUCT_A]], ptr %[[THIS]])387// LLVM:   %[[LAM_RET:.*]] = call i32 @_ZZN1A3fooEvENKUlvE_clEv(ptr %[[LAM_ALLOCA]])388// LLVM:   store i32 %[[LAM_RET]], ptr %[[RETVAL]]389// LLVM:   br label %[[RET_BB:.*]]390// LLVM: [[RET_BB]]:391// LLVM:   %[[RET:.*]] = load i32, ptr %[[RETVAL]]392// LLVM:   ret i32 %[[RET]]393 394// OGCG: define linkonce_odr noundef i32 @_ZN1A3fooEv(ptr {{.*}} %[[THIS_ARG:.*]])395// OGCG:   %[[THIS_ALLOCA:.*]] = alloca ptr396// OGCG:   %[[LAM_ALLOCA:.*]] =  alloca %[[REC_LAM_A:.*]],397// OGCG:   store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]398// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]399// OGCG:   %[[STRUCT_A:.*]] = getelementptr inbounds nuw %[[REC_LAM_A]], ptr %[[LAM_ALLOCA]], i32 0, i32 0400// OGCG:   call void @llvm.memcpy.p0.p0.i64(ptr {{.*}} %[[STRUCT_A]], ptr {{.*}} %[[THIS]], i64 4, i1 false)401// OGCG:   %[[LAM_RET:.*]] = call noundef i32 @_ZZN1A3fooEvENKUlvE_clEv(ptr {{.*}} %[[LAM_ALLOCA]])402// OGCG:   ret i32 %[[LAM_RET]]403 404// lambda operator() in bar()405// CIR: cir.func {{.*}} @_ZZN1A3barEvENKUlvE_clEv(%[[THIS_ARG2:.*]]: !cir.ptr<![[REC_LAM_PTR_A:.*]]> {{.*}}) -> !s32i {{.*}} {406// CIR:   %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<![[REC_LAM_PTR_A]]>, !cir.ptr<!cir.ptr<![[REC_LAM_PTR_A]]>>, ["this", init]407// CIR:   %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]408// CIR:   cir.store{{.*}} %[[THIS_ARG]], %[[THIS_ADDR]]409// CIR:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]410// CIR:   %[[STRUCT_A_ADDR_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "this"}411// CIR:   %[[STRUCT_A_ADDR:.*]] = cir.load{{.*}} %[[STRUCT_A_ADDR_ADDR]]412// CIR:   %[[A_A_ADDR:.*]] = cir.get_member %[[STRUCT_A_ADDR]][0] {name = "a"}413// CIR:   %[[A_A:.*]] = cir.load{{.*}} %[[A_A_ADDR]]414// CIR:   cir.store{{.*}} %[[A_A]], %[[RETVAL]]415// CIR:   %[[RET:.*]] = cir.load{{.*}} %[[RETVAL]]416// CIR:   cir.return %[[RET]]417 418// LLVM: define linkonce_odr i32 @_ZZN1A3barEvENKUlvE_clEv(ptr %[[THIS_ARG:.*]])419// LLVM:   %[[THIS_ALLOCA:.*]]  = alloca ptr420// LLVM:   %[[RETVAL:.*]] = alloca i32421// LLVM:   store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]422// LLVM:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]423// LLVM:   %[[STRUCT_A_ADDRR_ADDR:.*]] = getelementptr %[[REC_LAM_PTR_A:.*]], ptr %[[THIS]], i32 0, i32 0424// LLVM:   %[[STRUCT_A_ADDR:.*]] = load ptr, ptr %[[STRUCT_A_ADDRR_ADDR]]425// LLVM:   %[[A_A_ADDR:.*]] = getelementptr %struct.A, ptr %[[STRUCT_A_ADDR]], i32 0, i32 0426// LLVM:   %[[A_A:.*]] = load i32, ptr %[[A_A_ADDR]]427// LLVM:   store i32 %[[A_A]], ptr %[[RETVAL]]428// LLVM:   %[[RET:.*]] = load i32, ptr %[[RETVAL]]429// LLVM:   ret i32 %[[RET]]430 431// The function above is defined after _ZZN1A3fooEvENKUlvE_clEv in OGCG, see below.432 433// A::bar()434// CIR: cir.func {{.*}} @_ZN1A3barEv(%[[THIS_ARG:.*]]: !cir.ptr<!rec_A> {{.*}}) -> !s32i {{.*}} {435// CIR:   %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_A>, !cir.ptr<!cir.ptr<!rec_A>>, ["this", init]436// CIR:   %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]437// CIR:   cir.store %[[THIS_ARG]], %[[THIS_ADDR]]438// CIR:   %[[THIS]] = cir.load %[[THIS_ADDR]] : !cir.ptr<!cir.ptr<!rec_A>>, !cir.ptr<!rec_A>439// CIR:   cir.scope {440// CIR:     %[[LAM_ADDR:.*]] = cir.alloca ![[REC_LAM_PTR_A]], !cir.ptr<![[REC_LAM_PTR_A]]>, ["ref.tmp0"]441// CIR:     %[[A_ADDR_ADDR:.*]] = cir.get_member %[[LAM_ADDR]][0] {name = "this"} : !cir.ptr<![[REC_LAM_PTR_A]]> -> !cir.ptr<!cir.ptr<!rec_A>>442// CIR:     cir.store{{.*}} %[[THIS]], %[[A_ADDR_ADDR]]443// CIR:     %[[LAM_RET:.*]] = cir.call @_ZZN1A3barEvENKUlvE_clEv(%[[LAM_ADDR]])444// CIR:     cir.store{{.*}} %[[LAM_RET]], %[[RETVAL]]445// CIR:   }446// CIR:   %[[RET:.*]] = cir.load{{.*}} %[[RETVAL]]447// CIR:   cir.return %[[RET]]448 449// LLVM: define linkonce_odr i32 @_ZN1A3barEv(ptr %[[THIS_ARG:.*]])450// LLVM:   %[[LAM_ALLOCA:.*]] =  alloca %[[REC_LAM_PTR_A]]451// LLVM:   %[[THIS_ALLOCA:.*]] = alloca ptr452// LLVM:   %[[RETVAL:.*]] = alloca i32453// LLVM:   store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]454// LLVM:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]455// LLVM:   br label %[[SCOPE_BB:.*]]456// LLVM: [[SCOPE_BB]]:457// LLVM:   %[[A_ADDR_ADDR:.*]] = getelementptr %[[REC_LAM_PTR_A]], ptr %[[LAM_ALLOCA]], i32 0, i32 0458// LLVM:   store ptr %[[THIS]], ptr %[[A_ADDR_ADDR]]459// LLVM:   %[[LAM_RET:.*]] = call i32 @_ZZN1A3barEvENKUlvE_clEv(ptr %[[LAM_ALLOCA]])460// LLVM:   store i32 %[[LAM_RET]], ptr %[[RETVAL]]461// LLVM:   br label %[[RET_BB:.*]]462// LLVM: [[RET_BB]]:463// LLVM:   %[[RET:.*]] = load i32, ptr %[[RETVAL]]464// LLVM:   ret i32 %[[RET]]465 466// OGCG: define linkonce_odr noundef i32 @_ZN1A3barEv(ptr {{.*}} %[[THIS_ARG:.*]])467// OGCG:   %[[THIS_ALLOCA:.*]] = alloca ptr468// OGCG:   %[[LAM_ALLOCA:.*]] =  alloca %[[REC_LAM_PTR_A:.*]],469// OGCG:   store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]470// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]471// OGCG:   %[[STRUCT_A:.*]] = getelementptr inbounds nuw %[[REC_LAM_PTR_A]], ptr %[[LAM_ALLOCA]], i32 0, i32 0472// OGCG:   store ptr %[[THIS]], ptr %[[STRUCT_A]]473// OGCG:   %[[LAM_RET:.*]] = call noundef i32 @_ZZN1A3barEvENKUlvE_clEv(ptr {{.*}} %[[LAM_ALLOCA]])474// OGCG:   ret i32 %[[LAM_RET]]475 476// OGCG: define linkonce_odr noundef i32 @_ZZN1A3fooEvENKUlvE_clEv(ptr {{.*}} %[[THIS_ARG:.*]])477// OGCG:   %[[THIS_ALLOCA:.*]]  = alloca ptr478// OGCG:   store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]479// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]480// OGCG:   %[[PTR_A:.*]] = getelementptr inbounds nuw %[[REC_LAM_A]], ptr %[[THIS]], i32 0, i32 0481// OGCG:   %[[A_A_ADDR:.*]] = getelementptr inbounds nuw %struct.A, ptr %[[PTR_A]], i32 0, i32 0482// OGCG:   %[[A_A:.*]] = load i32, ptr %[[A_A_ADDR]]483// OGCG:   ret i32 %[[A_A]]484 485// OGCG: define linkonce_odr noundef i32 @_ZZN1A3barEvENKUlvE_clEv(ptr {{.*}} %[[THIS_ARG:.*]])486// OGCG:   %[[THIS_ALLOCA:.*]]  = alloca ptr487// OGCG:   store ptr %[[THIS_ARG]], ptr %[[THIS_ALLOCA]]488// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ALLOCA]]489// OGCG:   %[[A_ADDR_ADDR:.*]] = getelementptr inbounds nuw %[[REC_LAM_PTR_A]], ptr %[[THIS]], i32 0, i32 0490// OGCG:   %[[A_ADDR:.*]] = load ptr, ptr %[[A_ADDR_ADDR]]491// OGCG:   %[[A_A_ADDR:.*]] = getelementptr inbounds nuw %struct.A, ptr %[[A_ADDR]], i32 0, i32 0492// OGCG:   %[[A_A:.*]] = load i32, ptr %[[A_A_ADDR]]493// OGCG:   ret i32 %[[A_A]]494 495int test_lambda_this1(){496  struct A clsA;497  int x = clsA.foo();498  int y = clsA.bar();499  return x+y;500}501 502// CIR: cir.func {{.*}} @_Z17test_lambda_this1v{{.*}} {503// CIR:   cir.call @_ZN1AC1Ev(%[[A_THIS:.*]]){{.*}} : (!cir.ptr<!rec_A>) -> ()504// CIR:   cir.call @_ZN1A3fooEv(%[[A_THIS]]){{.*}} : (!cir.ptr<!rec_A>) -> !s32i505// CIR:   cir.call @_ZN1A3barEv(%[[A_THIS]]){{.*}} : (!cir.ptr<!rec_A>) -> !s32i506 507// LLVM: define {{.*}} i32 @_Z17test_lambda_this1v508// LLVM:   %[[A_THIS:.*]] = alloca %struct.A509// LLVM:   call void @_ZN1AC1Ev(ptr %[[A_THIS]])510// LLVM:   call i32 @_ZN1A3fooEv(ptr %[[A_THIS]])511// LLVM:   call i32 @_ZN1A3barEv(ptr %[[A_THIS]])512 513// The function above is define before lambda operator() in foo() in OGCG, see above.514