https://github.com/haopliu updated https://github.com/llvm/llvm-project/pull/74777
>From bb5acad16c6a627d73a5af96e3dd4eba2ebe1a5d Mon Sep 17 00:00:00 2001 From: Haopeng Liu <haop...@google.com> Date: Thu, 7 Dec 2023 21:25:33 +0000 Subject: [PATCH 1/4] Add size filter for stack auto init --- .../include/clang/Basic/DiagnosticDriverKinds.td | 7 +++++++ clang/include/clang/Basic/LangOptions.def | 2 ++ clang/include/clang/Driver/Options.td | 4 ++++ clang/lib/CodeGen/CGDecl.cpp | 9 +++++++++ clang/lib/Driver/ToolChains/Clang.cpp | 15 +++++++++++++++ clang/test/Driver/clang_f_opts.c | 13 +++++++++++++ 6 files changed, 50 insertions(+) diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 676f1a62b49dd..5fd097154d0fa 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -656,6 +656,13 @@ def err_drv_trivial_auto_var_init_stop_after_missing_dependency : Error< def err_drv_trivial_auto_var_init_stop_after_invalid_value : Error< "'-ftrivial-auto-var-init-stop-after=*' only accepts positive integers">; +def err_drv_trivial_auto_var_init_size_bound_missing_dependency : Error< + "'-ftrivial-auto-var-init-size-bound=*' is used without " + "'-ftrivial-auto-var-init=zero' or '-ftrivial-auto-var-init=pattern'">; + +def err_drv_trivial_auto_var_init_size_bound_invalid_value : Error< + "'-ftrivial-auto-var-init-size-bound=*' only accepts positive integers (in bytes)">; + def warn_drv_msp430_hwmult_unsupported : Warning< "the given MCU does not support hardware multiply, but '-mhwmult' is set to " "%0">, InGroup<InvalidCommandLineArgument>; diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index c3d5399905a3f..8325561fc6d23 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -376,6 +376,8 @@ ENUM_LANGOPT(TrivialAutoVarInit, TrivialAutoVarInitKind, 2, TrivialAutoVarInitKi "trivial automatic variable initialization") VALUE_LANGOPT(TrivialAutoVarInitStopAfter, 32, 0, "stop trivial automatic variable initialization after the specified number of instances. Must be greater than 0.") +VALUE_LANGOPT(TrivialAutoVarInitSizeBound, 32, 0, + "stop trivial automatic variable initialization if var size exceeds the specified number of instances (in bytes). Must be greater than 0.") ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined, "signed integer overflow handling") ENUM_LANGOPT(ThreadModel , ThreadModelKind, 2, ThreadModelKind::POSIX, "Thread Model") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 0eec2b3526376..f92dbd07de20d 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3627,6 +3627,10 @@ def ftrivial_auto_var_init_stop_after : Joined<["-"], "ftrivial-auto-var-init-st Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>, HelpText<"Stop initializing trivial automatic stack variables after the specified number of instances">, MarshallingInfoInt<LangOpts<"TrivialAutoVarInitStopAfter">>; +def ftrivial_auto_var_init_size_bound : Joined<["-"], "ftrivial-auto-var-init-size-bound=">, Group<f_Group>, + Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>, + HelpText<"Stop initializing trivial automatic stack variables if var size exceeds the specified number of instances (in bytes)">, + MarshallingInfoInt<LangOpts<"TrivialAutoVarInitSizeBound">>; def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>, Visibility<[ClangOption, CLOption, DXCOption]>, HelpText<"Emit full debug info for all types used by the program">; diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index a5da0aa2965a0..1f9650e60d5e0 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1759,20 +1759,29 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type, const VarDecl &D, Address Loc) { auto trivialAutoVarInit = getContext().getLangOpts().getTrivialAutoVarInit(); + auto trivialAutoVarInitSizeBound = + getContext().getLangOpts().TrivialAutoVarInitSizeBound; CharUnits Size = getContext().getTypeSizeInChars(type); bool isVolatile = type.isVolatileQualified(); if (!Size.isZero()) { + auto allocSize = CGM.getDataLayout().getTypeAllocSize(Loc.getElementType()); switch (trivialAutoVarInit) { case LangOptions::TrivialAutoVarInitKind::Uninitialized: llvm_unreachable("Uninitialized handled by caller"); case LangOptions::TrivialAutoVarInitKind::Zero: if (CGM.stopAutoInit()) return; + if (trivialAutoVarInitSizeBound > 0 && + allocSize >= trivialAutoVarInitSizeBound) + return; emitStoresForZeroInit(CGM, D, Loc, isVolatile, Builder); break; case LangOptions::TrivialAutoVarInitKind::Pattern: if (CGM.stopAutoInit()) return; + if (trivialAutoVarInitSizeBound > 0 && + allocSize >= trivialAutoVarInitSizeBound) + return; emitStoresForPatternInit(CGM, D, Loc, isVolatile, Builder); break; } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index f02f7c841b91f..669c85c8c7722 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3436,6 +3436,21 @@ static void RenderTrivialAutoVarInitOptions(const Driver &D, CmdArgs.push_back( Args.MakeArgString("-ftrivial-auto-var-init-stop-after=" + Val)); } + + if (Arg *A = + Args.getLastArg(options::OPT_ftrivial_auto_var_init_size_bound)) { + if (!Args.hasArg(options::OPT_ftrivial_auto_var_init) || + StringRef( + Args.getLastArg(options::OPT_ftrivial_auto_var_init)->getValue()) == + "uninitialized") + D.Diag(diag::err_drv_trivial_auto_var_init_size_bound_missing_dependency); + A->claim(); + StringRef Val = A->getValue(); + if (std::stoi(Val.str()) <= 0) + D.Diag(diag::err_drv_trivial_auto_var_init_size_bound_invalid_value); + CmdArgs.push_back( + Args.MakeArgString("-ftrivial-auto-var-init-size-bound=" + Val)); + } } static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs, diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c index ebe8a0520bf0f..7f947d2de5c6e 100644 --- a/clang/test/Driver/clang_f_opts.c +++ b/clang/test/Driver/clang_f_opts.c @@ -585,6 +585,19 @@ // CHECK-TRIVIAL-PATTERN-STOP-AFTER-INVALID-VALUE: only accepts positive integers // CHECK-TRIVIAL-ZERO-STOP-AFTER-INVALID-VALUE: only accepts positive integers +// RUN: %clang -### -S -ftrivial-auto-var-init=pattern -ftrivial-auto-var-init-size-bound=1024 %s 2>&1 | FileCheck -check-prefix=CHECK-TRIVIAL-PATTERN-SIZE-BOUND %s +// RUN: %clang -### -S -ftrivial-auto-var-init=zero -ftrivial-auto-var-init-size-bound=1024 %s 2>&1 | FileCheck -check-prefix=CHECK-TRIVIAL-ZERO-SIZE-BOUND %s +// RUN: not %clang -### -S -ftrivial-auto-var-init-size-bound=1024 %s 2>&1 | FileCheck -check-prefix=CHECK-TRIVIAL-SIZE-BOUND-MISSING-DEPENDENCY %s +// RUN: not %clang -### -S -ftrivial-auto-var-init=pattern -ftrivial-auto-var-init-size-bound=0 %s 2>&1 | FileCheck -check-prefix=CHECK-TRIVIAL-PATTERN-SIZE-BOUND-INVALID-VALUE %s +// RUN: not %clang -### -S -ftrivial-auto-var-init=zero -ftrivial-auto-var-init-size-bound=0 %s 2>&1 | FileCheck -check-prefix=CHECK-TRIVIAL-ZERO-SIZE-BOUND-INVALID-VALUE %s +// CHECK-TRIVIAL-PATTERN-SIZE-BOUND-NOT: is used without '-ftrivial-auto-var-init' +// CHECK-TRIVIAL-PATTERN-SIZE-BOUND-NOT: only accepts positive integers (in bytes) +// CHECK-TRIVIAL-ZERO-SIZE-BOUND-NOT: is used without '-ftrivial-auto-var-init' +// CHECK-TRIVIAL-ZERO-SIZE-BOUND-NOT: only accepts positive integers (in bytes) +// CHECK-TRIVIAL-SIZE-BOUND-MISSING-DEPENDENCY: used without '-ftrivial-auto-var-init=zero' or +// CHECK-TRIVIAL-PATTERN-SIZE-BOUND-INVALID-VALUE: only accepts positive integers (in bytes) +// CHECK-TRIVIAL-ZERO-SIZE-BOUND-INVALID-VALUE: only accepts positive integers (in bytes) + // RUN: %clang -### -S -fno-temp-file %s 2>&1 | FileCheck -check-prefix=CHECK-NO-TEMP-FILE %s // CHECK-NO-TEMP-FILE: "-fno-temp-file" >From 00af66353d938c6ce59dada49c8bededb06ac4fc Mon Sep 17 00:00:00 2001 From: Haopeng Liu <haop...@google.com> Date: Thu, 7 Dec 2023 21:30:07 +0000 Subject: [PATCH 2/4] Add size filter for stack auto init --- .../CodeGenCXX/auto-var-init-size-bound.cpp | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 clang/test/CodeGenCXX/auto-var-init-size-bound.cpp diff --git a/clang/test/CodeGenCXX/auto-var-init-size-bound.cpp b/clang/test/CodeGenCXX/auto-var-init-size-bound.cpp new file mode 100644 index 0000000000000..1f6c2b143d397 --- /dev/null +++ b/clang/test/CodeGenCXX/auto-var-init-size-bound.cpp @@ -0,0 +1,82 @@ +// Pattern related size bound tests: 1, 8, 4096, 4097 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=pattern -ftrivial-auto-var-init-size-bound=1 %s -emit-llvm -o - | FileCheck -check-prefix=PATTERN-COMMON -check-prefix=PATTERN-BOUND-1 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=pattern -ftrivial-auto-var-init-size-bound=8 %s -emit-llvm -o - | FileCheck -check-prefix=PATTERN-COMMON -check-prefix=PATTERN-BOUND-8 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=pattern -ftrivial-auto-var-init-size-bound=4096 %s -emit-llvm -o - | FileCheck -check-prefix=PATTERN-COMMON -check-prefix=PATTERN-BOUND-4096 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=pattern -ftrivial-auto-var-init-size-bound=4097 %s -emit-llvm -o - | FileCheck -check-prefix=PATTERN-COMMON -check-prefix=PATTERN-BOUND-4097 %s +// +// Zero related size bound tests: 1, 8, 4096, 4097 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=zero -ftrivial-auto-var-init-size-bound=1 %s -emit-llvm -o - | FileCheck -check-prefix=ZERO-COMMON -check-prefix=ZERO-BOUND-1 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=zero -ftrivial-auto-var-init-size-bound=8 %s -emit-llvm -o - | FileCheck -check-prefix=ZERO-COMMON -check-prefix=ZERO-BOUND-8 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=zero -ftrivial-auto-var-init-size-bound=4096 %s -emit-llvm -o - | FileCheck -check-prefix=ZERO-COMMON -check-prefix=ZERO-BOUND-4096 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=zero -ftrivial-auto-var-init-size-bound=4097 %s -emit-llvm -o - | FileCheck -check-prefix=ZERO-COMMON -check-prefix=ZERO-BOUND-4097 %s + +#define ARRLEN 1024 + +int foo(unsigned n) { + bool var_size_1; + long var_size_8 = 123; + void *var_size_8p; + int var_size_4096[ARRLEN]; + // VLA, non-constant size + int var_vla[n]; + // builtin, non-constant size + var_size_8p = __builtin_alloca(sizeof(unsigned long long) * n); + // There are 6 variables: var_size_1, var_size_8, var_size_8p, var_size_4096, + // var_vla, and a builtin anonymous var ("%5"). + // "var_vla" and "%5" have a non-constant size, and they should be auto-inited + // disregarding the size bound. + // - Size bound 1: "var_vla" and "%5" + // - Size bound 8: "var_size_1", "var_vla", and "%5" + // - Size bound 4096: "var_size_1", "var_size_8", "var_size_8p", + // "var_vla", and "%5" + // - Size bound 4097: "var_size_1", "var_size_8", "var_size_8p", + // "var_size_4096", "var_vla", and "%5" + // + // PATTERN-BOUND-1-NOT: store i8 -86, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-1-NOT: store i64 -6148914691236517206, ptr %var_size_8, align 8, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-1-NOT: store ptr inttoptr (i64 -6148914691236517206 to ptr), ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-1-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 -86, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]] + + // PATTERN-BOUND-8: store i8 -86, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-8-NOT: store i64 -6148914691236517206, ptr %var_size_8, align 8, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-8-NOT: store ptr inttoptr (i64 -6148914691236517206 to ptr), ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-8-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 -86, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]] + + // PATTERN-BOUND-4096: store i8 -86, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-4096: store i64 -6148914691236517206, ptr %var_size_8, align 8, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-4096: store ptr inttoptr (i64 -6148914691236517206 to ptr), ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-4096-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 -86, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]] + + // PATTERN-BOUND-4097: store i8 -86, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-4097: store i64 -6148914691236517206, ptr %var_size_8, align 8, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-4097: store ptr inttoptr (i64 -6148914691236517206 to ptr), ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]] + // PATTERN-BOUND-4097: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 -86, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]] + + // PATTERN-COMMON: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %vla.cur, ptr align 4 @__const._Z3fooj.var_vla, i64 4, i1 false), !annotation [[AUTO_INIT:!.+]] + // PATTERN-COMMON: call void @llvm.memset.p0.i64(ptr align 16 %5, i8 -86, i64 %mul, i1 false), !annotation [[AUTO_INIT:!.+]] + + // ZERO-BOUND-1-NOT: store i8 0, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-1-NOT: store i64 0, ptr %var_size_8, align 8, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-1-NOT: store ptr null, ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-1-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 0, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]] + + // ZERO-BOUND-8: store i8 0, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-8-NOT: store i64 0, ptr %var_size_8, align 8, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-8-NOT: store ptr null, ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-8-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 0, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]] + + // ZERO-BOUND-4096: store i8 0, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-4096: store i64 0, ptr %var_size_8, align 8, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-4096: store ptr null, ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-4096-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 0, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]] + + // ZERO-BOUND-4097: store i8 0, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-4097: store i64 0, ptr %var_size_8, align 8, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-4097: store ptr null, ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]] + // ZERO-BOUND-4097: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 0, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]] + + // ZERO-COMMON: call void @llvm.memset.p0.i64(ptr align 16 %vla, i8 0, i64 %3, i1 false), !annotation [[AUTO_INIT:!.+]] + // ZERO-COMMON: call void @llvm.memset.p0.i64(ptr align 16 %5, i8 0, i64 %mul, i1 false), !annotation [[AUTO_INIT:!.+]] + + return 0; +} >From 3443a97756ceeea8405c31899fded0d719f112b2 Mon Sep 17 00:00:00 2001 From: Haopeng Liu <haop...@google.com> Date: Thu, 7 Dec 2023 22:54:22 +0000 Subject: [PATCH 3/4] Fix the clang-format warning --- clang/lib/CodeGen/CGDecl.cpp | 552 +++++++++++++++++------------------ 1 file changed, 275 insertions(+), 277 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 1f9650e60d5e0..d64ced5382b4b 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -109,7 +109,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { if (cast<RecordDecl>(D).getDefinition()) DI->EmitAndRetainType(getContext().getRecordType(cast<RecordDecl>(&D))); return; - case Decl::Enum: // enum X; + case Decl::Enum: // enum X; if (CGDebugInfo *DI = getDebugInfo()) if (cast<EnumDecl>(D).getDefinition()) DI->EmitAndRetainType(getContext().getEnumType(cast<EnumDecl>(&D))); @@ -119,7 +119,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::StaticAssert: // static_assert(X, ""); [C++0x] case Decl::Label: // __label__ x; case Decl::Import: - case Decl::MSGuid: // __declspec(uuid("...")) + case Decl::MSGuid: // __declspec(uuid("...")) case Decl::UnnamedGlobalConstant: case Decl::TemplateParamObject: case Decl::OMPThreadPrivate: @@ -136,11 +136,11 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::NamespaceAlias: if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(D)); + DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(D)); return; - case Decl::Using: // using X; [C++] + case Decl::Using: // using X; [C++] if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitUsingDecl(cast<UsingDecl>(D)); + DI->EmitUsingDecl(cast<UsingDecl>(D)); return; case Decl::UsingEnum: // using enum X; [C++] if (CGDebugInfo *DI = getDebugInfo()) @@ -173,8 +173,8 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::OMPDeclareMapper: return CGM.EmitOMPDeclareMapper(cast<OMPDeclareMapperDecl>(&D), this); - case Decl::Typedef: // typedef int X; - case Decl::TypeAlias: { // using X = int; [C++0x] + case Decl::Typedef: // typedef int X; + case Decl::TypeAlias: { // using X = int; [C++0x] QualType Ty = cast<TypedefNameDecl>(D).getUnderlyingType(); if (CGDebugInfo *DI = getDebugInfo()) DI->EmitAndRetainType(Ty); @@ -353,7 +353,7 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, // be constant. GV->setConstant(false); - EmitCXXGuardedInit(D, GV, /*PerformInit*/true); + EmitCXXGuardedInit(D, GV, /*PerformInit*/ true); } return GV; } @@ -405,14 +405,14 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, // We have a constant initializer, but a nontrivial destructor. We still // need to perform a guarded "initialization" in order to register the // destructor. - EmitCXXGuardedInit(D, GV, /*PerformInit*/false); + EmitCXXGuardedInit(D, GV, /*PerformInit*/ false); } return GV; } -void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, - llvm::GlobalValue::LinkageTypes Linkage) { +void CodeGenFunction::EmitStaticVarDecl( + const VarDecl &D, llvm::GlobalValue::LinkageTypes Linkage) { // Check to see if we already have a global variable for this // declaration. This can happen when double-emitting function // bodies, e.g. with complete and base constructors. @@ -434,7 +434,7 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, llvm::Type *expectedType = addr->getType(); llvm::GlobalVariable *var = - cast<llvm::GlobalVariable>(addr->stripPointerCasts()); + cast<llvm::GlobalVariable>(addr->stripPointerCasts()); // CUDA's local and local static __shared__ variables should not // have any non-empty initializers. This is ensured by Sema. @@ -477,7 +477,7 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, // FIXME: It is really dangerous to store this in the map; if anyone // RAUW's the GV uses of this constant will be invalid. llvm::Constant *castedAddr = - llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(var, expectedType); + llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(var, expectedType); LocalDeclMap.find(&D)->second = Address(castedAddr, elemTy, alignment); CGM.setStaticLocalDeclAddress(&D, castedAddr); @@ -492,153 +492,149 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, } namespace { - struct DestroyObject final : EHScopeStack::Cleanup { - DestroyObject(Address addr, QualType type, - CodeGenFunction::Destroyer *destroyer, - bool useEHCleanupForArray) +struct DestroyObject final : EHScopeStack::Cleanup { + DestroyObject(Address addr, QualType type, + CodeGenFunction::Destroyer *destroyer, + bool useEHCleanupForArray) : addr(addr), type(type), destroyer(destroyer), useEHCleanupForArray(useEHCleanupForArray) {} - Address addr; - QualType type; - CodeGenFunction::Destroyer *destroyer; - bool useEHCleanupForArray; + Address addr; + QualType type; + CodeGenFunction::Destroyer *destroyer; + bool useEHCleanupForArray; - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Don't use an EH cleanup recursively from an EH cleanup. - bool useEHCleanupForArray = + void Emit(CodeGenFunction &CGF, Flags flags) override { + // Don't use an EH cleanup recursively from an EH cleanup. + bool useEHCleanupForArray = flags.isForNormalCleanup() && this->useEHCleanupForArray; - CGF.emitDestroy(addr, type, destroyer, useEHCleanupForArray); - } - }; + CGF.emitDestroy(addr, type, destroyer, useEHCleanupForArray); + } +}; - template <class Derived> - struct DestroyNRVOVariable : EHScopeStack::Cleanup { - DestroyNRVOVariable(Address addr, QualType type, llvm::Value *NRVOFlag) - : NRVOFlag(NRVOFlag), Loc(addr), Ty(type) {} - - llvm::Value *NRVOFlag; - Address Loc; - QualType Ty; - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Along the exceptions path we always execute the dtor. - bool NRVO = flags.isForNormalCleanup() && NRVOFlag; - - llvm::BasicBlock *SkipDtorBB = nullptr; - if (NRVO) { - // If we exited via NRVO, we skip the destructor call. - llvm::BasicBlock *RunDtorBB = CGF.createBasicBlock("nrvo.unused"); - SkipDtorBB = CGF.createBasicBlock("nrvo.skipdtor"); - llvm::Value *DidNRVO = - CGF.Builder.CreateFlagLoad(NRVOFlag, "nrvo.val"); - CGF.Builder.CreateCondBr(DidNRVO, SkipDtorBB, RunDtorBB); - CGF.EmitBlock(RunDtorBB); - } +template <class Derived> struct DestroyNRVOVariable : EHScopeStack::Cleanup { + DestroyNRVOVariable(Address addr, QualType type, llvm::Value *NRVOFlag) + : NRVOFlag(NRVOFlag), Loc(addr), Ty(type) {} + + llvm::Value *NRVOFlag; + Address Loc; + QualType Ty; - static_cast<Derived *>(this)->emitDestructorCall(CGF); + void Emit(CodeGenFunction &CGF, Flags flags) override { + // Along the exceptions path we always execute the dtor. + bool NRVO = flags.isForNormalCleanup() && NRVOFlag; - if (NRVO) CGF.EmitBlock(SkipDtorBB); + llvm::BasicBlock *SkipDtorBB = nullptr; + if (NRVO) { + // If we exited via NRVO, we skip the destructor call. + llvm::BasicBlock *RunDtorBB = CGF.createBasicBlock("nrvo.unused"); + SkipDtorBB = CGF.createBasicBlock("nrvo.skipdtor"); + llvm::Value *DidNRVO = CGF.Builder.CreateFlagLoad(NRVOFlag, "nrvo.val"); + CGF.Builder.CreateCondBr(DidNRVO, SkipDtorBB, RunDtorBB); + CGF.EmitBlock(RunDtorBB); } - virtual ~DestroyNRVOVariable() = default; - }; + static_cast<Derived *>(this)->emitDestructorCall(CGF); - struct DestroyNRVOVariableCXX final - : DestroyNRVOVariable<DestroyNRVOVariableCXX> { - DestroyNRVOVariableCXX(Address addr, QualType type, - const CXXDestructorDecl *Dtor, llvm::Value *NRVOFlag) - : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, type, NRVOFlag), - Dtor(Dtor) {} + if (NRVO) + CGF.EmitBlock(SkipDtorBB); + } - const CXXDestructorDecl *Dtor; + virtual ~DestroyNRVOVariable() = default; +}; - void emitDestructorCall(CodeGenFunction &CGF) { - CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, - /*ForVirtualBase=*/false, - /*Delegating=*/false, Loc, Ty); - } - }; +struct DestroyNRVOVariableCXX final + : DestroyNRVOVariable<DestroyNRVOVariableCXX> { + DestroyNRVOVariableCXX(Address addr, QualType type, + const CXXDestructorDecl *Dtor, llvm::Value *NRVOFlag) + : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, type, NRVOFlag), + Dtor(Dtor) {} - struct DestroyNRVOVariableC final - : DestroyNRVOVariable<DestroyNRVOVariableC> { - DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty) - : DestroyNRVOVariable<DestroyNRVOVariableC>(addr, Ty, NRVOFlag) {} + const CXXDestructorDecl *Dtor; - void emitDestructorCall(CodeGenFunction &CGF) { - CGF.destroyNonTrivialCStruct(CGF, Loc, Ty); - } - }; + void emitDestructorCall(CodeGenFunction &CGF) { + CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, + /*ForVirtualBase=*/false, + /*Delegating=*/false, Loc, Ty); + } +}; - struct CallStackRestore final : EHScopeStack::Cleanup { - Address Stack; - CallStackRestore(Address Stack) : Stack(Stack) {} - bool isRedundantBeforeReturn() override { return true; } - void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::Value *V = CGF.Builder.CreateLoad(Stack); - CGF.Builder.CreateStackRestore(V); - } - }; +struct DestroyNRVOVariableC final : DestroyNRVOVariable<DestroyNRVOVariableC> { + DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty) + : DestroyNRVOVariable<DestroyNRVOVariableC>(addr, Ty, NRVOFlag) {} - struct KmpcAllocFree final : EHScopeStack::Cleanup { - std::pair<llvm::Value *, llvm::Value *> AddrSizePair; - KmpcAllocFree(const std::pair<llvm::Value *, llvm::Value *> &AddrSizePair) - : AddrSizePair(AddrSizePair) {} - void Emit(CodeGenFunction &CGF, Flags EmissionFlags) override { - auto &RT = CGF.CGM.getOpenMPRuntime(); - RT.getKmpcFreeShared(CGF, AddrSizePair); - } - }; + void emitDestructorCall(CodeGenFunction &CGF) { + CGF.destroyNonTrivialCStruct(CGF, Loc, Ty); + } +}; - struct ExtendGCLifetime final : EHScopeStack::Cleanup { - const VarDecl &Var; - ExtendGCLifetime(const VarDecl *var) : Var(*var) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Compute the address of the local variable, in case it's a - // byref or something. - DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false, - Var.getType(), VK_LValue, SourceLocation()); - llvm::Value *value = CGF.EmitLoadOfScalar(CGF.EmitDeclRefLValue(&DRE), - SourceLocation()); - CGF.EmitExtendGCLifetime(value); - } - }; +struct CallStackRestore final : EHScopeStack::Cleanup { + Address Stack; + CallStackRestore(Address Stack) : Stack(Stack) {} + bool isRedundantBeforeReturn() override { return true; } + void Emit(CodeGenFunction &CGF, Flags flags) override { + llvm::Value *V = CGF.Builder.CreateLoad(Stack); + CGF.Builder.CreateStackRestore(V); + } +}; + +struct KmpcAllocFree final : EHScopeStack::Cleanup { + std::pair<llvm::Value *, llvm::Value *> AddrSizePair; + KmpcAllocFree(const std::pair<llvm::Value *, llvm::Value *> &AddrSizePair) + : AddrSizePair(AddrSizePair) {} + void Emit(CodeGenFunction &CGF, Flags EmissionFlags) override { + auto &RT = CGF.CGM.getOpenMPRuntime(); + RT.getKmpcFreeShared(CGF, AddrSizePair); + } +}; - struct CallCleanupFunction final : EHScopeStack::Cleanup { - llvm::Constant *CleanupFn; - const CGFunctionInfo &FnInfo; - const VarDecl &Var; +struct ExtendGCLifetime final : EHScopeStack::Cleanup { + const VarDecl &Var; + ExtendGCLifetime(const VarDecl *var) : Var(*var) {} - CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info, - const VarDecl *Var) + void Emit(CodeGenFunction &CGF, Flags flags) override { + // Compute the address of the local variable, in case it's a + // byref or something. + DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false, + Var.getType(), VK_LValue, SourceLocation()); + llvm::Value *value = + CGF.EmitLoadOfScalar(CGF.EmitDeclRefLValue(&DRE), SourceLocation()); + CGF.EmitExtendGCLifetime(value); + } +}; + +struct CallCleanupFunction final : EHScopeStack::Cleanup { + llvm::Constant *CleanupFn; + const CGFunctionInfo &FnInfo; + const VarDecl &Var; + + CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info, + const VarDecl *Var) : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var) {} - void Emit(CodeGenFunction &CGF, Flags flags) override { - DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false, - Var.getType(), VK_LValue, SourceLocation()); - // Compute the address of the local variable, in case it's a byref - // or something. - llvm::Value *Addr = CGF.EmitDeclRefLValue(&DRE).getPointer(CGF); - - // In some cases, the type of the function argument will be different from - // the type of the pointer. An example of this is - // void f(void* arg); - // __attribute__((cleanup(f))) void *g; - // - // To fix this we insert a bitcast here. - QualType ArgTy = FnInfo.arg_begin()->type; - llvm::Value *Arg = - CGF.Builder.CreateBitCast(Addr, CGF.ConvertType(ArgTy)); - - CallArgList Args; - Args.add(RValue::get(Arg), - CGF.getContext().getPointerType(Var.getType())); - auto Callee = CGCallee::forDirect(CleanupFn); - CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args); - } - }; + void Emit(CodeGenFunction &CGF, Flags flags) override { + DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false, + Var.getType(), VK_LValue, SourceLocation()); + // Compute the address of the local variable, in case it's a byref + // or something. + llvm::Value *Addr = CGF.EmitDeclRefLValue(&DRE).getPointer(CGF); + + // In some cases, the type of the function argument will be different from + // the type of the pointer. An example of this is + // void f(void* arg); + // __attribute__((cleanup(f))) void *g; + // + // To fix this we insert a bitcast here. + QualType ArgTy = FnInfo.arg_begin()->type; + llvm::Value *Arg = CGF.Builder.CreateBitCast(Addr, CGF.ConvertType(ArgTy)); + + CallArgList Args; + Args.add(RValue::get(Arg), CGF.getContext().getPointerType(Var.getType())); + auto Callee = CGCallee::forDirect(CleanupFn); + CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args); + } +}; } // end anonymous namespace /// EmitAutoVarWithLifetime - Does the setup required for an automatic @@ -656,9 +652,9 @@ static void EmitAutoVarWithLifetime(CodeGenFunction &CGF, const VarDecl &var, case Qualifiers::OCL_Strong: { CodeGenFunction::Destroyer *destroyer = - (var.hasAttr<ObjCPreciseLifetimeAttr>() - ? CodeGenFunction::destroyARCStrongPrecise - : CodeGenFunction::destroyARCStrongImprecise); + (var.hasAttr<ObjCPreciseLifetimeAttr>() + ? CodeGenFunction::destroyARCStrongPrecise + : CodeGenFunction::destroyARCStrongImprecise); CleanupKind cleanupKind = CGF.getARCCleanupKind(); CGF.pushDestroy(cleanupKind, addr, var.getType(), destroyer, @@ -705,14 +701,16 @@ static bool isAccessedBy(const VarDecl &var, const Stmt *s) { } static bool isAccessedBy(const ValueDecl *decl, const Expr *e) { - if (!decl) return false; - if (!isa<VarDecl>(decl)) return false; + if (!decl) + return false; + if (!isa<VarDecl>(decl)) + return false; const VarDecl *var = cast<VarDecl>(decl); return isAccessedBy(*var, e); } -static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, - const LValue &destLV, const Expr *init) { +static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, const LValue &destLV, + const Expr *init) { bool needsCast = false; while (auto castExpr = dyn_cast<CastExpr>(init->IgnoreParens())) { @@ -761,8 +759,7 @@ static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, return false; } -static void drillIntoBlockVariable(CodeGenFunction &CGF, - LValue &lvalue, +static void drillIntoBlockVariable(CodeGenFunction &CGF, LValue &lvalue, const VarDecl *var) { lvalue.setAddress(CGF.emitBlockByrefAddress(lvalue.getAddress(CGF), var)); } @@ -875,7 +872,8 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D, // disappear in the common case. value = EmitScalarExpr(init); - if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); + if (capturedByInit) + drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); if (accessedByInit) EmitARCStoreWeak(lvalue.getAddress(*this), value, /*ignored*/ true); else @@ -888,7 +886,8 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D, break; } - if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); + if (capturedByInit) + drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); EmitNullabilityCheck(lvalue, value, init->getExprLoc()); @@ -911,8 +910,7 @@ static bool canEmitInitWithFewStoresAfterBZero(llvm::Constant *Init, unsigned &NumStores) { // Zero and Undef never requires any extra stores. if (isa<llvm::ConstantAggregateZero>(Init) || - isa<llvm::ConstantPointerNull>(Init) || - isa<llvm::UndefValue>(Init)) + isa<llvm::ConstantPointerNull>(Init) || isa<llvm::UndefValue>(Init)) return true; if (isa<llvm::ConstantInt>(Init) || isa<llvm::ConstantFP>(Init) || isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) || @@ -930,7 +928,7 @@ static bool canEmitInitWithFewStoresAfterBZero(llvm::Constant *Init, } if (llvm::ConstantDataSequential *CDS = - dyn_cast<llvm::ConstantDataSequential>(Init)) { + dyn_cast<llvm::ConstantDataSequential>(Init)) { for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) { llvm::Constant *Elt = CDS->getElementAsConstant(i); if (!canEmitInitWithFewStoresAfterBZero(Elt, NumStores)) @@ -995,7 +993,8 @@ static void emitStoresForInitAfterBZero(CodeGenModule &CGM, static bool shouldUseBZeroPlusStoresToInitialize(llvm::Constant *Init, uint64_t GlobalSize) { // If a global is all zeros, always use a bzero. - if (isa<llvm::ConstantAggregateZero>(Init)) return true; + if (isa<llvm::ConstantAggregateZero>(Init)) + return true; // If a non-zero global is <= 32 bytes, always use a memcpy. If it is large, // do it if it will require 6 or fewer scalar stores. @@ -1714,20 +1713,19 @@ static bool isCapturedBy(const VarDecl &Var, const Expr *E) { if (const auto *BIE = dyn_cast<Expr>(BI)) { if (isCapturedBy(Var, BIE)) return true; - } - else if (const auto *DS = dyn_cast<DeclStmt>(BI)) { - // special case declarations - for (const auto *I : DS->decls()) { - if (const auto *VD = dyn_cast<VarDecl>((I))) { - const Expr *Init = VD->getInit(); - if (Init && isCapturedBy(Var, Init)) - return true; - } + } else if (const auto *DS = dyn_cast<DeclStmt>(BI)) { + // special case declarations + for (const auto *I : DS->decls()) { + if (const auto *VD = dyn_cast<VarDecl>((I))) { + const Expr *Init = VD->getInit(); + if (Init && isCapturedBy(Var, Init)) + return true; } - } - else - // FIXME. Make safe assumption assuming arbitrary statements cause capturing. - // Later, provide code to poke into statements for capture analysis. + } + } else + // FIXME. Make safe assumption assuming arbitrary statements cause + // capturing. Later, provide code to poke into statements for capture + // analysis. return true; return false; } @@ -1747,8 +1745,7 @@ bool CodeGenFunction::isTrivialInitializer(const Expr *Init) { if (const CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) if (CXXConstructorDecl *Constructor = Construct->getConstructor()) - if (Constructor->isTrivial() && - Constructor->isDefaultConstructor() && + if (Constructor->isTrivial() && Constructor->isDefaultConstructor() && !Construct->requiresZeroInitialization()) return true; @@ -1759,7 +1756,7 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type, const VarDecl &D, Address Loc) { auto trivialAutoVarInit = getContext().getLangOpts().getTrivialAutoVarInit(); - auto trivialAutoVarInitSizeBound = + auto trivialAutoVarInitSizeBound = getContext().getLangOpts().TrivialAutoVarInitSizeBound; CharUnits Size = getContext().getTypeSizeInChars(type); bool isVolatile = type.isVolatileQualified(); @@ -1861,7 +1858,8 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { assert(emission.Variable && "emission was not valid!"); // If this was emitted as a global constant, we're done. - if (emission.wasEmittedAsGlobal()) return; + if (emission.wasEmittedAsGlobal()) + return; const VarDecl &D = *emission.Variable; auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, D.getLocation()); @@ -1873,7 +1871,8 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { // If we are at an unreachable point, we don't need to emit the initializer // unless it contains a label. if (!HaveInsertPoint()) { - if (!Init || !ContainsLabel(Init)) return; + if (!Init || !ContainsLabel(Init)) + return; EnsureInsertPoint(); } @@ -1884,9 +1883,8 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { // Initialize the variable here if it doesn't have a initializer and it is a // C struct that is non-trivial to initialize or an array containing such a // struct. - if (!Init && - type.isNonTrivialToPrimitiveDefaultInitialize() == - QualType::PDIK_Struct) { + if (!Init && type.isNonTrivialToPrimitiveDefaultInitialize() == + QualType::PDIK_Struct) { LValue Dst = MakeAddrLValue(emission.getAllocatedAddress(), type); if (emission.IsEscapingByRef) drillIntoBlockVariable(*this, Dst, &D); @@ -2003,7 +2001,7 @@ void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D, } case TEK_Aggregate: if (type->isAtomicType()) { - EmitAtomicInit(const_cast<Expr*>(init), lvalue); + EmitAtomicInit(const_cast<Expr *>(init), lvalue); } else { AggValueSlot::Overlap_t Overlap = AggValueSlot::MayOverlap; if (isa<VarDecl>(D)) @@ -2023,8 +2021,8 @@ void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D, /// Enter a destroy cleanup for the given local variable. void CodeGenFunction::emitAutoVarTypeCleanup( - const CodeGenFunction::AutoVarEmission &emission, - QualType::DestructionKind dtorKind) { + const CodeGenFunction::AutoVarEmission &emission, + QualType::DestructionKind dtorKind) { assert(dtorKind != QualType::DK_none); // Note that for __block variables, we want to destroy the @@ -2055,7 +2053,8 @@ void CodeGenFunction::emitAutoVarTypeCleanup( case QualType::DK_objc_strong_lifetime: // Suppress cleanups for pseudo-strong variables. - if (var->isARCPseudoStrong()) return; + if (var->isARCPseudoStrong()) + return; // Otherwise, consider whether to use an EH cleanup or not. cleanupKind = getARCCleanupKind(); @@ -2080,7 +2079,8 @@ void CodeGenFunction::emitAutoVarTypeCleanup( } // If we haven't chosen a more specific destroyer, use the default. - if (!destroyer) destroyer = getDestroyer(dtorKind); + if (!destroyer) + destroyer = getDestroyer(dtorKind); // Use an EH cleanup in array destructors iff the destructor itself // is being pushed as an EH cleanup. @@ -2093,11 +2093,13 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { assert(emission.Variable && "emission was not valid!"); // If this was emitted as a global constant, we're done. - if (emission.wasEmittedAsGlobal()) return; + if (emission.wasEmittedAsGlobal()) + return; // If we don't have an insertion point, we're done. Sema prevents // us from jumping into any of these scopes anyway. - if (!HaveInsertPoint()) return; + if (!HaveInsertPoint()) + return; const VarDecl &D = *emission.Variable; @@ -2139,7 +2141,8 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { CodeGenFunction::Destroyer * CodeGenFunction::getDestroyer(QualType::DestructionKind kind) { switch (kind) { - case QualType::DK_none: llvm_unreachable("no destroyer for trivial dtor"); + case QualType::DK_none: + llvm_unreachable("no destroyer for trivial dtor"); case QualType::DK_cxx_destructor: return destroyCXXObject; case QualType::DK_objc_strong_lifetime: @@ -2176,8 +2179,8 @@ void CodeGenFunction::pushDestroy(QualType::DestructionKind dtorKind, void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray) { - pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, - destroyer, useEHCleanupForArray); + pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, destroyer, + useEHCleanupForArray); } void CodeGenFunction::pushStackRestore(CleanupKind Kind, Address SPMem) { @@ -2205,7 +2208,8 @@ void CodeGenFunction::pushLifetimeExtendedDestroy(CleanupKind cleanupKind, destroyer, useEHCleanupForArray); return pushCleanupAfterFullExprWithActiveFlag<DestroyObject>( - cleanupKind, Address::invalid(), addr, type, destroyer, useEHCleanupForArray); + cleanupKind, Address::invalid(), addr, type, destroyer, + useEHCleanupForArray); } // Otherwise, we should only destroy the object if it's been initialized. @@ -2252,9 +2256,8 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type, llvm::Value *length = emitArrayLength(arrayType, type, addr); - CharUnits elementAlign = - addr.getAlignment() - .alignmentOfArrayElement(getContext().getTypeSizeInChars(type)); + CharUnits elementAlign = addr.getAlignment().alignmentOfArrayElement( + getContext().getTypeSizeInChars(type)); // Normally we have to check whether the array is zero-length. bool checkZeroLength = true; @@ -2262,15 +2265,16 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type, // But if the array length is constant, we can suppress that. if (llvm::ConstantInt *constLength = dyn_cast<llvm::ConstantInt>(length)) { // ...and if it's constant zero, we can just skip the entire thing. - if (constLength->isZero()) return; + if (constLength->isZero()) + return; checkZeroLength = false; } llvm::Value *begin = addr.getPointer(); llvm::Value *end = Builder.CreateInBoundsGEP(addr.getElementType(), begin, length); - emitArrayDestroy(begin, end, type, elementAlign, destroyer, - checkZeroLength, useEHCleanupForArray); + emitArrayDestroy(begin, end, type, elementAlign, destroyer, checkZeroLength, + useEHCleanupForArray); } /// emitArrayDestroy - Destroys all the elements of the given array, @@ -2283,8 +2287,7 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type, /// \param useEHCleanup - whether to push an EH cleanup to destroy /// the remaining elements in case the destruction of a single /// element throws -void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, - llvm::Value *end, +void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, llvm::Value *end, QualType elementType, CharUnits elementAlign, Destroyer *destroyer, @@ -2298,8 +2301,8 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, llvm::BasicBlock *doneBB = createBasicBlock("arraydestroy.done"); if (checkZeroLength) { - llvm::Value *isEmpty = Builder.CreateICmpEQ(begin, end, - "arraydestroy.isempty"); + llvm::Value *isEmpty = + Builder.CreateICmpEQ(begin, end, "arraydestroy.isempty"); Builder.CreateCondBr(isEmpty, doneBB, bodyBB); } @@ -2307,7 +2310,7 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); EmitBlock(bodyBB); llvm::PHINode *elementPast = - Builder.CreatePHI(begin->getType(), 2, "arraydestroy.elementPast"); + Builder.CreatePHI(begin->getType(), 2, "arraydestroy.elementPast"); elementPast->addIncoming(end, entryBB); // Shift the address back by one element. @@ -2338,9 +2341,9 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, /// Perform partial array destruction as if in an EH cleanup. Unlike /// emitArrayDestroy, the element type here may still be an array type. -static void emitPartialArrayDestroy(CodeGenFunction &CGF, - llvm::Value *begin, llvm::Value *end, - QualType type, CharUnits elementAlign, +static void emitPartialArrayDestroy(CodeGenFunction &CGF, llvm::Value *begin, + llvm::Value *end, QualType type, + CharUnits elementAlign, CodeGenFunction::Destroyer *destroyer) { llvm::Type *elemTy = CGF.ConvertTypeForMem(type); @@ -2356,11 +2359,11 @@ static void emitPartialArrayDestroy(CodeGenFunction &CGF, if (arrayDepth) { llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); - SmallVector<llvm::Value*,4> gepIndices(arrayDepth+1, zero); - begin = CGF.Builder.CreateInBoundsGEP( - elemTy, begin, gepIndices, "pad.arraybegin"); - end = CGF.Builder.CreateInBoundsGEP( - elemTy, end, gepIndices, "pad.arrayend"); + SmallVector<llvm::Value *, 4> gepIndices(arrayDepth + 1, zero); + begin = CGF.Builder.CreateInBoundsGEP(elemTy, begin, gepIndices, + "pad.arraybegin"); + end = + CGF.Builder.CreateInBoundsGEP(elemTy, end, gepIndices, "pad.arrayend"); } // Destroy the array. We don't ever need an EH cleanup because we @@ -2371,54 +2374,53 @@ static void emitPartialArrayDestroy(CodeGenFunction &CGF, } namespace { - /// RegularPartialArrayDestroy - a cleanup which performs a partial - /// array destroy where the end pointer is regularly determined and - /// does not need to be loaded from a local. - class RegularPartialArrayDestroy final : public EHScopeStack::Cleanup { - llvm::Value *ArrayBegin; - llvm::Value *ArrayEnd; - QualType ElementType; - CodeGenFunction::Destroyer *Destroyer; - CharUnits ElementAlign; - public: - RegularPartialArrayDestroy(llvm::Value *arrayBegin, llvm::Value *arrayEnd, +/// RegularPartialArrayDestroy - a cleanup which performs a partial +/// array destroy where the end pointer is regularly determined and +/// does not need to be loaded from a local. +class RegularPartialArrayDestroy final : public EHScopeStack::Cleanup { + llvm::Value *ArrayBegin; + llvm::Value *ArrayEnd; + QualType ElementType; + CodeGenFunction::Destroyer *Destroyer; + CharUnits ElementAlign; + +public: + RegularPartialArrayDestroy(llvm::Value *arrayBegin, llvm::Value *arrayEnd, + QualType elementType, CharUnits elementAlign, + CodeGenFunction::Destroyer *destroyer) + : ArrayBegin(arrayBegin), ArrayEnd(arrayEnd), ElementType(elementType), + Destroyer(destroyer), ElementAlign(elementAlign) {} + + void Emit(CodeGenFunction &CGF, Flags flags) override { + emitPartialArrayDestroy(CGF, ArrayBegin, ArrayEnd, ElementType, + ElementAlign, Destroyer); + } +}; + +/// IrregularPartialArrayDestroy - a cleanup which performs a +/// partial array destroy where the end pointer is irregularly +/// determined and must be loaded from a local. +class IrregularPartialArrayDestroy final : public EHScopeStack::Cleanup { + llvm::Value *ArrayBegin; + Address ArrayEndPointer; + QualType ElementType; + CodeGenFunction::Destroyer *Destroyer; + CharUnits ElementAlign; + +public: + IrregularPartialArrayDestroy(llvm::Value *arrayBegin, Address arrayEndPointer, QualType elementType, CharUnits elementAlign, CodeGenFunction::Destroyer *destroyer) - : ArrayBegin(arrayBegin), ArrayEnd(arrayEnd), - ElementType(elementType), Destroyer(destroyer), - ElementAlign(elementAlign) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - emitPartialArrayDestroy(CGF, ArrayBegin, ArrayEnd, - ElementType, ElementAlign, Destroyer); - } - }; - - /// IrregularPartialArrayDestroy - a cleanup which performs a - /// partial array destroy where the end pointer is irregularly - /// determined and must be loaded from a local. - class IrregularPartialArrayDestroy final : public EHScopeStack::Cleanup { - llvm::Value *ArrayBegin; - Address ArrayEndPointer; - QualType ElementType; - CodeGenFunction::Destroyer *Destroyer; - CharUnits ElementAlign; - public: - IrregularPartialArrayDestroy(llvm::Value *arrayBegin, - Address arrayEndPointer, - QualType elementType, - CharUnits elementAlign, - CodeGenFunction::Destroyer *destroyer) : ArrayBegin(arrayBegin), ArrayEndPointer(arrayEndPointer), ElementType(elementType), Destroyer(destroyer), ElementAlign(elementAlign) {} - void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::Value *arrayEnd = CGF.Builder.CreateLoad(ArrayEndPointer); - emitPartialArrayDestroy(CGF, ArrayBegin, arrayEnd, - ElementType, ElementAlign, Destroyer); - } - }; + void Emit(CodeGenFunction &CGF, Flags flags) override { + llvm::Value *arrayEnd = CGF.Builder.CreateLoad(ArrayEndPointer); + emitPartialArrayDestroy(CGF, ArrayBegin, arrayEnd, ElementType, + ElementAlign, Destroyer); + } +}; } // end anonymous namespace /// pushIrregularPartialArrayCleanup - Push an EH cleanup to destroy @@ -2432,10 +2434,9 @@ void CodeGenFunction::pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin, QualType elementType, CharUnits elementAlign, Destroyer *destroyer) { - pushFullExprCleanup<IrregularPartialArrayDestroy>(EHCleanup, - arrayBegin, arrayEndPointer, - elementType, elementAlign, - destroyer); + pushFullExprCleanup<IrregularPartialArrayDestroy>( + EHCleanup, arrayBegin, arrayEndPointer, elementType, elementAlign, + destroyer); } /// pushRegularPartialArrayCleanup - Push an EH cleanup to destroy @@ -2449,18 +2450,16 @@ void CodeGenFunction::pushRegularPartialArrayCleanup(llvm::Value *arrayBegin, QualType elementType, CharUnits elementAlign, Destroyer *destroyer) { - pushFullExprCleanup<RegularPartialArrayDestroy>(EHCleanup, - arrayBegin, arrayEnd, - elementType, elementAlign, - destroyer); + pushFullExprCleanup<RegularPartialArrayDestroy>( + EHCleanup, arrayBegin, arrayEnd, elementType, elementAlign, destroyer); } /// Lazily declare the @llvm.lifetime.start intrinsic. llvm::Function *CodeGenModule::getLLVMLifetimeStartFn() { if (LifetimeStartFn) return LifetimeStartFn; - LifetimeStartFn = llvm::Intrinsic::getDeclaration(&getModule(), - llvm::Intrinsic::lifetime_start, AllocaInt8PtrTy); + LifetimeStartFn = llvm::Intrinsic::getDeclaration( + &getModule(), llvm::Intrinsic::lifetime_start, AllocaInt8PtrTy); return LifetimeStartFn; } @@ -2468,28 +2467,27 @@ llvm::Function *CodeGenModule::getLLVMLifetimeStartFn() { llvm::Function *CodeGenModule::getLLVMLifetimeEndFn() { if (LifetimeEndFn) return LifetimeEndFn; - LifetimeEndFn = llvm::Intrinsic::getDeclaration(&getModule(), - llvm::Intrinsic::lifetime_end, AllocaInt8PtrTy); + LifetimeEndFn = llvm::Intrinsic::getDeclaration( + &getModule(), llvm::Intrinsic::lifetime_end, AllocaInt8PtrTy); return LifetimeEndFn; } namespace { - /// A cleanup to perform a release of an object at the end of a - /// function. This is used to balance out the incoming +1 of a - /// ns_consumed argument when we can't reasonably do that just by - /// not doing the initial retain for a __block argument. - struct ConsumeARCParameter final : EHScopeStack::Cleanup { - ConsumeARCParameter(llvm::Value *param, - ARCPreciseLifetime_t precise) +/// A cleanup to perform a release of an object at the end of a +/// function. This is used to balance out the incoming +1 of a +/// ns_consumed argument when we can't reasonably do that just by +/// not doing the initial retain for a __block argument. +struct ConsumeARCParameter final : EHScopeStack::Cleanup { + ConsumeARCParameter(llvm::Value *param, ARCPreciseLifetime_t precise) : Param(param), Precise(precise) {} - llvm::Value *Param; - ARCPreciseLifetime_t Precise; + llvm::Value *Param; + ARCPreciseLifetime_t Precise; - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitARCRelease(Param, Precise); - } - }; + void Emit(CodeGenFunction &CGF, Flags flags) override { + CGF.EmitARCRelease(Param, Precise); + } +}; } // end anonymous namespace /// Emit an alloca (or GlobalValue depending on target) @@ -2633,18 +2631,18 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, EmitStoreOfScalar(Null, lv, /* isInitialization */ true); EmitARCStoreStrongCall(lv.getAddress(*this), ArgVal, true); DoStore = false; - } - else - // Don't use objc_retainBlock for block pointers, because we - // don't want to Block_copy something just because we got it - // as a parameter. + } else + // Don't use objc_retainBlock for block pointers, because we + // don't want to Block_copy something just because we got it + // as a parameter. ArgVal = EmitARCRetainNonBlock(ArgVal); } } else { // Push the cleanup for a consumed parameter. if (isConsumed) { - ARCPreciseLifetime_t precise = (D.hasAttr<ObjCPreciseLifetimeAttr>() - ? ARCPreciseLifetime : ARCImpreciseLifetime); + ARCPreciseLifetime_t precise = + (D.hasAttr<ObjCPreciseLifetimeAttr>() ? ARCPreciseLifetime + : ARCImpreciseLifetime); EHStack.pushCleanup<ConsumeARCParameter>(getARCCleanupKind(), ArgVal, precise); } >From 17a0eec59b63ed495b3722086d5ecb47d870899e Mon Sep 17 00:00:00 2001 From: Haopeng Liu <haop...@google.com> Date: Thu, 7 Dec 2023 23:12:10 +0000 Subject: [PATCH 4/4] Revert the clang-format change ;-) --- clang/lib/CodeGen/CGDecl.cpp | 552 ++++++++++++++++++----------------- 1 file changed, 277 insertions(+), 275 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index d64ced5382b4b..1f9650e60d5e0 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -109,7 +109,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { if (cast<RecordDecl>(D).getDefinition()) DI->EmitAndRetainType(getContext().getRecordType(cast<RecordDecl>(&D))); return; - case Decl::Enum: // enum X; + case Decl::Enum: // enum X; if (CGDebugInfo *DI = getDebugInfo()) if (cast<EnumDecl>(D).getDefinition()) DI->EmitAndRetainType(getContext().getEnumType(cast<EnumDecl>(&D))); @@ -119,7 +119,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::StaticAssert: // static_assert(X, ""); [C++0x] case Decl::Label: // __label__ x; case Decl::Import: - case Decl::MSGuid: // __declspec(uuid("...")) + case Decl::MSGuid: // __declspec(uuid("...")) case Decl::UnnamedGlobalConstant: case Decl::TemplateParamObject: case Decl::OMPThreadPrivate: @@ -136,11 +136,11 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::NamespaceAlias: if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(D)); + DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(D)); return; - case Decl::Using: // using X; [C++] + case Decl::Using: // using X; [C++] if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitUsingDecl(cast<UsingDecl>(D)); + DI->EmitUsingDecl(cast<UsingDecl>(D)); return; case Decl::UsingEnum: // using enum X; [C++] if (CGDebugInfo *DI = getDebugInfo()) @@ -173,8 +173,8 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::OMPDeclareMapper: return CGM.EmitOMPDeclareMapper(cast<OMPDeclareMapperDecl>(&D), this); - case Decl::Typedef: // typedef int X; - case Decl::TypeAlias: { // using X = int; [C++0x] + case Decl::Typedef: // typedef int X; + case Decl::TypeAlias: { // using X = int; [C++0x] QualType Ty = cast<TypedefNameDecl>(D).getUnderlyingType(); if (CGDebugInfo *DI = getDebugInfo()) DI->EmitAndRetainType(Ty); @@ -353,7 +353,7 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, // be constant. GV->setConstant(false); - EmitCXXGuardedInit(D, GV, /*PerformInit*/ true); + EmitCXXGuardedInit(D, GV, /*PerformInit*/true); } return GV; } @@ -405,14 +405,14 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, // We have a constant initializer, but a nontrivial destructor. We still // need to perform a guarded "initialization" in order to register the // destructor. - EmitCXXGuardedInit(D, GV, /*PerformInit*/ false); + EmitCXXGuardedInit(D, GV, /*PerformInit*/false); } return GV; } -void CodeGenFunction::EmitStaticVarDecl( - const VarDecl &D, llvm::GlobalValue::LinkageTypes Linkage) { +void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, + llvm::GlobalValue::LinkageTypes Linkage) { // Check to see if we already have a global variable for this // declaration. This can happen when double-emitting function // bodies, e.g. with complete and base constructors. @@ -434,7 +434,7 @@ void CodeGenFunction::EmitStaticVarDecl( llvm::Type *expectedType = addr->getType(); llvm::GlobalVariable *var = - cast<llvm::GlobalVariable>(addr->stripPointerCasts()); + cast<llvm::GlobalVariable>(addr->stripPointerCasts()); // CUDA's local and local static __shared__ variables should not // have any non-empty initializers. This is ensured by Sema. @@ -477,7 +477,7 @@ void CodeGenFunction::EmitStaticVarDecl( // FIXME: It is really dangerous to store this in the map; if anyone // RAUW's the GV uses of this constant will be invalid. llvm::Constant *castedAddr = - llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(var, expectedType); + llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(var, expectedType); LocalDeclMap.find(&D)->second = Address(castedAddr, elemTy, alignment); CGM.setStaticLocalDeclAddress(&D, castedAddr); @@ -492,149 +492,153 @@ void CodeGenFunction::EmitStaticVarDecl( } namespace { -struct DestroyObject final : EHScopeStack::Cleanup { - DestroyObject(Address addr, QualType type, - CodeGenFunction::Destroyer *destroyer, - bool useEHCleanupForArray) + struct DestroyObject final : EHScopeStack::Cleanup { + DestroyObject(Address addr, QualType type, + CodeGenFunction::Destroyer *destroyer, + bool useEHCleanupForArray) : addr(addr), type(type), destroyer(destroyer), useEHCleanupForArray(useEHCleanupForArray) {} - Address addr; - QualType type; - CodeGenFunction::Destroyer *destroyer; - bool useEHCleanupForArray; + Address addr; + QualType type; + CodeGenFunction::Destroyer *destroyer; + bool useEHCleanupForArray; - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Don't use an EH cleanup recursively from an EH cleanup. - bool useEHCleanupForArray = + void Emit(CodeGenFunction &CGF, Flags flags) override { + // Don't use an EH cleanup recursively from an EH cleanup. + bool useEHCleanupForArray = flags.isForNormalCleanup() && this->useEHCleanupForArray; - CGF.emitDestroy(addr, type, destroyer, useEHCleanupForArray); - } -}; - -template <class Derived> struct DestroyNRVOVariable : EHScopeStack::Cleanup { - DestroyNRVOVariable(Address addr, QualType type, llvm::Value *NRVOFlag) - : NRVOFlag(NRVOFlag), Loc(addr), Ty(type) {} - - llvm::Value *NRVOFlag; - Address Loc; - QualType Ty; - - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Along the exceptions path we always execute the dtor. - bool NRVO = flags.isForNormalCleanup() && NRVOFlag; - - llvm::BasicBlock *SkipDtorBB = nullptr; - if (NRVO) { - // If we exited via NRVO, we skip the destructor call. - llvm::BasicBlock *RunDtorBB = CGF.createBasicBlock("nrvo.unused"); - SkipDtorBB = CGF.createBasicBlock("nrvo.skipdtor"); - llvm::Value *DidNRVO = CGF.Builder.CreateFlagLoad(NRVOFlag, "nrvo.val"); - CGF.Builder.CreateCondBr(DidNRVO, SkipDtorBB, RunDtorBB); - CGF.EmitBlock(RunDtorBB); + CGF.emitDestroy(addr, type, destroyer, useEHCleanupForArray); } + }; - static_cast<Derived *>(this)->emitDestructorCall(CGF); + template <class Derived> + struct DestroyNRVOVariable : EHScopeStack::Cleanup { + DestroyNRVOVariable(Address addr, QualType type, llvm::Value *NRVOFlag) + : NRVOFlag(NRVOFlag), Loc(addr), Ty(type) {} + + llvm::Value *NRVOFlag; + Address Loc; + QualType Ty; + + void Emit(CodeGenFunction &CGF, Flags flags) override { + // Along the exceptions path we always execute the dtor. + bool NRVO = flags.isForNormalCleanup() && NRVOFlag; + + llvm::BasicBlock *SkipDtorBB = nullptr; + if (NRVO) { + // If we exited via NRVO, we skip the destructor call. + llvm::BasicBlock *RunDtorBB = CGF.createBasicBlock("nrvo.unused"); + SkipDtorBB = CGF.createBasicBlock("nrvo.skipdtor"); + llvm::Value *DidNRVO = + CGF.Builder.CreateFlagLoad(NRVOFlag, "nrvo.val"); + CGF.Builder.CreateCondBr(DidNRVO, SkipDtorBB, RunDtorBB); + CGF.EmitBlock(RunDtorBB); + } - if (NRVO) - CGF.EmitBlock(SkipDtorBB); - } + static_cast<Derived *>(this)->emitDestructorCall(CGF); - virtual ~DestroyNRVOVariable() = default; -}; + if (NRVO) CGF.EmitBlock(SkipDtorBB); + } -struct DestroyNRVOVariableCXX final - : DestroyNRVOVariable<DestroyNRVOVariableCXX> { - DestroyNRVOVariableCXX(Address addr, QualType type, - const CXXDestructorDecl *Dtor, llvm::Value *NRVOFlag) - : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, type, NRVOFlag), - Dtor(Dtor) {} + virtual ~DestroyNRVOVariable() = default; + }; - const CXXDestructorDecl *Dtor; + struct DestroyNRVOVariableCXX final + : DestroyNRVOVariable<DestroyNRVOVariableCXX> { + DestroyNRVOVariableCXX(Address addr, QualType type, + const CXXDestructorDecl *Dtor, llvm::Value *NRVOFlag) + : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, type, NRVOFlag), + Dtor(Dtor) {} - void emitDestructorCall(CodeGenFunction &CGF) { - CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, - /*ForVirtualBase=*/false, - /*Delegating=*/false, Loc, Ty); - } -}; + const CXXDestructorDecl *Dtor; -struct DestroyNRVOVariableC final : DestroyNRVOVariable<DestroyNRVOVariableC> { - DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty) - : DestroyNRVOVariable<DestroyNRVOVariableC>(addr, Ty, NRVOFlag) {} + void emitDestructorCall(CodeGenFunction &CGF) { + CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, + /*ForVirtualBase=*/false, + /*Delegating=*/false, Loc, Ty); + } + }; - void emitDestructorCall(CodeGenFunction &CGF) { - CGF.destroyNonTrivialCStruct(CGF, Loc, Ty); - } -}; + struct DestroyNRVOVariableC final + : DestroyNRVOVariable<DestroyNRVOVariableC> { + DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty) + : DestroyNRVOVariable<DestroyNRVOVariableC>(addr, Ty, NRVOFlag) {} -struct CallStackRestore final : EHScopeStack::Cleanup { - Address Stack; - CallStackRestore(Address Stack) : Stack(Stack) {} - bool isRedundantBeforeReturn() override { return true; } - void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::Value *V = CGF.Builder.CreateLoad(Stack); - CGF.Builder.CreateStackRestore(V); - } -}; + void emitDestructorCall(CodeGenFunction &CGF) { + CGF.destroyNonTrivialCStruct(CGF, Loc, Ty); + } + }; -struct KmpcAllocFree final : EHScopeStack::Cleanup { - std::pair<llvm::Value *, llvm::Value *> AddrSizePair; - KmpcAllocFree(const std::pair<llvm::Value *, llvm::Value *> &AddrSizePair) - : AddrSizePair(AddrSizePair) {} - void Emit(CodeGenFunction &CGF, Flags EmissionFlags) override { - auto &RT = CGF.CGM.getOpenMPRuntime(); - RT.getKmpcFreeShared(CGF, AddrSizePair); - } -}; + struct CallStackRestore final : EHScopeStack::Cleanup { + Address Stack; + CallStackRestore(Address Stack) : Stack(Stack) {} + bool isRedundantBeforeReturn() override { return true; } + void Emit(CodeGenFunction &CGF, Flags flags) override { + llvm::Value *V = CGF.Builder.CreateLoad(Stack); + CGF.Builder.CreateStackRestore(V); + } + }; -struct ExtendGCLifetime final : EHScopeStack::Cleanup { - const VarDecl &Var; - ExtendGCLifetime(const VarDecl *var) : Var(*var) {} + struct KmpcAllocFree final : EHScopeStack::Cleanup { + std::pair<llvm::Value *, llvm::Value *> AddrSizePair; + KmpcAllocFree(const std::pair<llvm::Value *, llvm::Value *> &AddrSizePair) + : AddrSizePair(AddrSizePair) {} + void Emit(CodeGenFunction &CGF, Flags EmissionFlags) override { + auto &RT = CGF.CGM.getOpenMPRuntime(); + RT.getKmpcFreeShared(CGF, AddrSizePair); + } + }; - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Compute the address of the local variable, in case it's a - // byref or something. - DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false, - Var.getType(), VK_LValue, SourceLocation()); - llvm::Value *value = - CGF.EmitLoadOfScalar(CGF.EmitDeclRefLValue(&DRE), SourceLocation()); - CGF.EmitExtendGCLifetime(value); - } -}; + struct ExtendGCLifetime final : EHScopeStack::Cleanup { + const VarDecl &Var; + ExtendGCLifetime(const VarDecl *var) : Var(*var) {} + + void Emit(CodeGenFunction &CGF, Flags flags) override { + // Compute the address of the local variable, in case it's a + // byref or something. + DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false, + Var.getType(), VK_LValue, SourceLocation()); + llvm::Value *value = CGF.EmitLoadOfScalar(CGF.EmitDeclRefLValue(&DRE), + SourceLocation()); + CGF.EmitExtendGCLifetime(value); + } + }; -struct CallCleanupFunction final : EHScopeStack::Cleanup { - llvm::Constant *CleanupFn; - const CGFunctionInfo &FnInfo; - const VarDecl &Var; + struct CallCleanupFunction final : EHScopeStack::Cleanup { + llvm::Constant *CleanupFn; + const CGFunctionInfo &FnInfo; + const VarDecl &Var; - CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info, - const VarDecl *Var) + CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info, + const VarDecl *Var) : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var) {} - void Emit(CodeGenFunction &CGF, Flags flags) override { - DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false, - Var.getType(), VK_LValue, SourceLocation()); - // Compute the address of the local variable, in case it's a byref - // or something. - llvm::Value *Addr = CGF.EmitDeclRefLValue(&DRE).getPointer(CGF); - - // In some cases, the type of the function argument will be different from - // the type of the pointer. An example of this is - // void f(void* arg); - // __attribute__((cleanup(f))) void *g; - // - // To fix this we insert a bitcast here. - QualType ArgTy = FnInfo.arg_begin()->type; - llvm::Value *Arg = CGF.Builder.CreateBitCast(Addr, CGF.ConvertType(ArgTy)); - - CallArgList Args; - Args.add(RValue::get(Arg), CGF.getContext().getPointerType(Var.getType())); - auto Callee = CGCallee::forDirect(CleanupFn); - CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args); - } -}; + void Emit(CodeGenFunction &CGF, Flags flags) override { + DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false, + Var.getType(), VK_LValue, SourceLocation()); + // Compute the address of the local variable, in case it's a byref + // or something. + llvm::Value *Addr = CGF.EmitDeclRefLValue(&DRE).getPointer(CGF); + + // In some cases, the type of the function argument will be different from + // the type of the pointer. An example of this is + // void f(void* arg); + // __attribute__((cleanup(f))) void *g; + // + // To fix this we insert a bitcast here. + QualType ArgTy = FnInfo.arg_begin()->type; + llvm::Value *Arg = + CGF.Builder.CreateBitCast(Addr, CGF.ConvertType(ArgTy)); + + CallArgList Args; + Args.add(RValue::get(Arg), + CGF.getContext().getPointerType(Var.getType())); + auto Callee = CGCallee::forDirect(CleanupFn); + CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args); + } + }; } // end anonymous namespace /// EmitAutoVarWithLifetime - Does the setup required for an automatic @@ -652,9 +656,9 @@ static void EmitAutoVarWithLifetime(CodeGenFunction &CGF, const VarDecl &var, case Qualifiers::OCL_Strong: { CodeGenFunction::Destroyer *destroyer = - (var.hasAttr<ObjCPreciseLifetimeAttr>() - ? CodeGenFunction::destroyARCStrongPrecise - : CodeGenFunction::destroyARCStrongImprecise); + (var.hasAttr<ObjCPreciseLifetimeAttr>() + ? CodeGenFunction::destroyARCStrongPrecise + : CodeGenFunction::destroyARCStrongImprecise); CleanupKind cleanupKind = CGF.getARCCleanupKind(); CGF.pushDestroy(cleanupKind, addr, var.getType(), destroyer, @@ -701,16 +705,14 @@ static bool isAccessedBy(const VarDecl &var, const Stmt *s) { } static bool isAccessedBy(const ValueDecl *decl, const Expr *e) { - if (!decl) - return false; - if (!isa<VarDecl>(decl)) - return false; + if (!decl) return false; + if (!isa<VarDecl>(decl)) return false; const VarDecl *var = cast<VarDecl>(decl); return isAccessedBy(*var, e); } -static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, const LValue &destLV, - const Expr *init) { +static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, + const LValue &destLV, const Expr *init) { bool needsCast = false; while (auto castExpr = dyn_cast<CastExpr>(init->IgnoreParens())) { @@ -759,7 +761,8 @@ static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, const LValue &destLV, return false; } -static void drillIntoBlockVariable(CodeGenFunction &CGF, LValue &lvalue, +static void drillIntoBlockVariable(CodeGenFunction &CGF, + LValue &lvalue, const VarDecl *var) { lvalue.setAddress(CGF.emitBlockByrefAddress(lvalue.getAddress(CGF), var)); } @@ -872,8 +875,7 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D, // disappear in the common case. value = EmitScalarExpr(init); - if (capturedByInit) - drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); + if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); if (accessedByInit) EmitARCStoreWeak(lvalue.getAddress(*this), value, /*ignored*/ true); else @@ -886,8 +888,7 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D, break; } - if (capturedByInit) - drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); + if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D)); EmitNullabilityCheck(lvalue, value, init->getExprLoc()); @@ -910,7 +911,8 @@ static bool canEmitInitWithFewStoresAfterBZero(llvm::Constant *Init, unsigned &NumStores) { // Zero and Undef never requires any extra stores. if (isa<llvm::ConstantAggregateZero>(Init) || - isa<llvm::ConstantPointerNull>(Init) || isa<llvm::UndefValue>(Init)) + isa<llvm::ConstantPointerNull>(Init) || + isa<llvm::UndefValue>(Init)) return true; if (isa<llvm::ConstantInt>(Init) || isa<llvm::ConstantFP>(Init) || isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) || @@ -928,7 +930,7 @@ static bool canEmitInitWithFewStoresAfterBZero(llvm::Constant *Init, } if (llvm::ConstantDataSequential *CDS = - dyn_cast<llvm::ConstantDataSequential>(Init)) { + dyn_cast<llvm::ConstantDataSequential>(Init)) { for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) { llvm::Constant *Elt = CDS->getElementAsConstant(i); if (!canEmitInitWithFewStoresAfterBZero(Elt, NumStores)) @@ -993,8 +995,7 @@ static void emitStoresForInitAfterBZero(CodeGenModule &CGM, static bool shouldUseBZeroPlusStoresToInitialize(llvm::Constant *Init, uint64_t GlobalSize) { // If a global is all zeros, always use a bzero. - if (isa<llvm::ConstantAggregateZero>(Init)) - return true; + if (isa<llvm::ConstantAggregateZero>(Init)) return true; // If a non-zero global is <= 32 bytes, always use a memcpy. If it is large, // do it if it will require 6 or fewer scalar stores. @@ -1713,19 +1714,20 @@ static bool isCapturedBy(const VarDecl &Var, const Expr *E) { if (const auto *BIE = dyn_cast<Expr>(BI)) { if (isCapturedBy(Var, BIE)) return true; - } else if (const auto *DS = dyn_cast<DeclStmt>(BI)) { - // special case declarations - for (const auto *I : DS->decls()) { - if (const auto *VD = dyn_cast<VarDecl>((I))) { - const Expr *Init = VD->getInit(); - if (Init && isCapturedBy(Var, Init)) - return true; + } + else if (const auto *DS = dyn_cast<DeclStmt>(BI)) { + // special case declarations + for (const auto *I : DS->decls()) { + if (const auto *VD = dyn_cast<VarDecl>((I))) { + const Expr *Init = VD->getInit(); + if (Init && isCapturedBy(Var, Init)) + return true; + } } - } - } else - // FIXME. Make safe assumption assuming arbitrary statements cause - // capturing. Later, provide code to poke into statements for capture - // analysis. + } + else + // FIXME. Make safe assumption assuming arbitrary statements cause capturing. + // Later, provide code to poke into statements for capture analysis. return true; return false; } @@ -1745,7 +1747,8 @@ bool CodeGenFunction::isTrivialInitializer(const Expr *Init) { if (const CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) if (CXXConstructorDecl *Constructor = Construct->getConstructor()) - if (Constructor->isTrivial() && Constructor->isDefaultConstructor() && + if (Constructor->isTrivial() && + Constructor->isDefaultConstructor() && !Construct->requiresZeroInitialization()) return true; @@ -1756,7 +1759,7 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type, const VarDecl &D, Address Loc) { auto trivialAutoVarInit = getContext().getLangOpts().getTrivialAutoVarInit(); - auto trivialAutoVarInitSizeBound = + auto trivialAutoVarInitSizeBound = getContext().getLangOpts().TrivialAutoVarInitSizeBound; CharUnits Size = getContext().getTypeSizeInChars(type); bool isVolatile = type.isVolatileQualified(); @@ -1858,8 +1861,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { assert(emission.Variable && "emission was not valid!"); // If this was emitted as a global constant, we're done. - if (emission.wasEmittedAsGlobal()) - return; + if (emission.wasEmittedAsGlobal()) return; const VarDecl &D = *emission.Variable; auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, D.getLocation()); @@ -1871,8 +1873,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { // If we are at an unreachable point, we don't need to emit the initializer // unless it contains a label. if (!HaveInsertPoint()) { - if (!Init || !ContainsLabel(Init)) - return; + if (!Init || !ContainsLabel(Init)) return; EnsureInsertPoint(); } @@ -1883,8 +1884,9 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { // Initialize the variable here if it doesn't have a initializer and it is a // C struct that is non-trivial to initialize or an array containing such a // struct. - if (!Init && type.isNonTrivialToPrimitiveDefaultInitialize() == - QualType::PDIK_Struct) { + if (!Init && + type.isNonTrivialToPrimitiveDefaultInitialize() == + QualType::PDIK_Struct) { LValue Dst = MakeAddrLValue(emission.getAllocatedAddress(), type); if (emission.IsEscapingByRef) drillIntoBlockVariable(*this, Dst, &D); @@ -2001,7 +2003,7 @@ void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D, } case TEK_Aggregate: if (type->isAtomicType()) { - EmitAtomicInit(const_cast<Expr *>(init), lvalue); + EmitAtomicInit(const_cast<Expr*>(init), lvalue); } else { AggValueSlot::Overlap_t Overlap = AggValueSlot::MayOverlap; if (isa<VarDecl>(D)) @@ -2021,8 +2023,8 @@ void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D, /// Enter a destroy cleanup for the given local variable. void CodeGenFunction::emitAutoVarTypeCleanup( - const CodeGenFunction::AutoVarEmission &emission, - QualType::DestructionKind dtorKind) { + const CodeGenFunction::AutoVarEmission &emission, + QualType::DestructionKind dtorKind) { assert(dtorKind != QualType::DK_none); // Note that for __block variables, we want to destroy the @@ -2053,8 +2055,7 @@ void CodeGenFunction::emitAutoVarTypeCleanup( case QualType::DK_objc_strong_lifetime: // Suppress cleanups for pseudo-strong variables. - if (var->isARCPseudoStrong()) - return; + if (var->isARCPseudoStrong()) return; // Otherwise, consider whether to use an EH cleanup or not. cleanupKind = getARCCleanupKind(); @@ -2079,8 +2080,7 @@ void CodeGenFunction::emitAutoVarTypeCleanup( } // If we haven't chosen a more specific destroyer, use the default. - if (!destroyer) - destroyer = getDestroyer(dtorKind); + if (!destroyer) destroyer = getDestroyer(dtorKind); // Use an EH cleanup in array destructors iff the destructor itself // is being pushed as an EH cleanup. @@ -2093,13 +2093,11 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { assert(emission.Variable && "emission was not valid!"); // If this was emitted as a global constant, we're done. - if (emission.wasEmittedAsGlobal()) - return; + if (emission.wasEmittedAsGlobal()) return; // If we don't have an insertion point, we're done. Sema prevents // us from jumping into any of these scopes anyway. - if (!HaveInsertPoint()) - return; + if (!HaveInsertPoint()) return; const VarDecl &D = *emission.Variable; @@ -2141,8 +2139,7 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { CodeGenFunction::Destroyer * CodeGenFunction::getDestroyer(QualType::DestructionKind kind) { switch (kind) { - case QualType::DK_none: - llvm_unreachable("no destroyer for trivial dtor"); + case QualType::DK_none: llvm_unreachable("no destroyer for trivial dtor"); case QualType::DK_cxx_destructor: return destroyCXXObject; case QualType::DK_objc_strong_lifetime: @@ -2179,8 +2176,8 @@ void CodeGenFunction::pushDestroy(QualType::DestructionKind dtorKind, void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray) { - pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, destroyer, - useEHCleanupForArray); + pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, + destroyer, useEHCleanupForArray); } void CodeGenFunction::pushStackRestore(CleanupKind Kind, Address SPMem) { @@ -2208,8 +2205,7 @@ void CodeGenFunction::pushLifetimeExtendedDestroy(CleanupKind cleanupKind, destroyer, useEHCleanupForArray); return pushCleanupAfterFullExprWithActiveFlag<DestroyObject>( - cleanupKind, Address::invalid(), addr, type, destroyer, - useEHCleanupForArray); + cleanupKind, Address::invalid(), addr, type, destroyer, useEHCleanupForArray); } // Otherwise, we should only destroy the object if it's been initialized. @@ -2256,8 +2252,9 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type, llvm::Value *length = emitArrayLength(arrayType, type, addr); - CharUnits elementAlign = addr.getAlignment().alignmentOfArrayElement( - getContext().getTypeSizeInChars(type)); + CharUnits elementAlign = + addr.getAlignment() + .alignmentOfArrayElement(getContext().getTypeSizeInChars(type)); // Normally we have to check whether the array is zero-length. bool checkZeroLength = true; @@ -2265,16 +2262,15 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type, // But if the array length is constant, we can suppress that. if (llvm::ConstantInt *constLength = dyn_cast<llvm::ConstantInt>(length)) { // ...and if it's constant zero, we can just skip the entire thing. - if (constLength->isZero()) - return; + if (constLength->isZero()) return; checkZeroLength = false; } llvm::Value *begin = addr.getPointer(); llvm::Value *end = Builder.CreateInBoundsGEP(addr.getElementType(), begin, length); - emitArrayDestroy(begin, end, type, elementAlign, destroyer, checkZeroLength, - useEHCleanupForArray); + emitArrayDestroy(begin, end, type, elementAlign, destroyer, + checkZeroLength, useEHCleanupForArray); } /// emitArrayDestroy - Destroys all the elements of the given array, @@ -2287,7 +2283,8 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type, /// \param useEHCleanup - whether to push an EH cleanup to destroy /// the remaining elements in case the destruction of a single /// element throws -void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, llvm::Value *end, +void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, + llvm::Value *end, QualType elementType, CharUnits elementAlign, Destroyer *destroyer, @@ -2301,8 +2298,8 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, llvm::Value *end, llvm::BasicBlock *doneBB = createBasicBlock("arraydestroy.done"); if (checkZeroLength) { - llvm::Value *isEmpty = - Builder.CreateICmpEQ(begin, end, "arraydestroy.isempty"); + llvm::Value *isEmpty = Builder.CreateICmpEQ(begin, end, + "arraydestroy.isempty"); Builder.CreateCondBr(isEmpty, doneBB, bodyBB); } @@ -2310,7 +2307,7 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, llvm::Value *end, llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); EmitBlock(bodyBB); llvm::PHINode *elementPast = - Builder.CreatePHI(begin->getType(), 2, "arraydestroy.elementPast"); + Builder.CreatePHI(begin->getType(), 2, "arraydestroy.elementPast"); elementPast->addIncoming(end, entryBB); // Shift the address back by one element. @@ -2341,9 +2338,9 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, llvm::Value *end, /// Perform partial array destruction as if in an EH cleanup. Unlike /// emitArrayDestroy, the element type here may still be an array type. -static void emitPartialArrayDestroy(CodeGenFunction &CGF, llvm::Value *begin, - llvm::Value *end, QualType type, - CharUnits elementAlign, +static void emitPartialArrayDestroy(CodeGenFunction &CGF, + llvm::Value *begin, llvm::Value *end, + QualType type, CharUnits elementAlign, CodeGenFunction::Destroyer *destroyer) { llvm::Type *elemTy = CGF.ConvertTypeForMem(type); @@ -2359,11 +2356,11 @@ static void emitPartialArrayDestroy(CodeGenFunction &CGF, llvm::Value *begin, if (arrayDepth) { llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); - SmallVector<llvm::Value *, 4> gepIndices(arrayDepth + 1, zero); - begin = CGF.Builder.CreateInBoundsGEP(elemTy, begin, gepIndices, - "pad.arraybegin"); - end = - CGF.Builder.CreateInBoundsGEP(elemTy, end, gepIndices, "pad.arrayend"); + SmallVector<llvm::Value*,4> gepIndices(arrayDepth+1, zero); + begin = CGF.Builder.CreateInBoundsGEP( + elemTy, begin, gepIndices, "pad.arraybegin"); + end = CGF.Builder.CreateInBoundsGEP( + elemTy, end, gepIndices, "pad.arrayend"); } // Destroy the array. We don't ever need an EH cleanup because we @@ -2374,53 +2371,54 @@ static void emitPartialArrayDestroy(CodeGenFunction &CGF, llvm::Value *begin, } namespace { -/// RegularPartialArrayDestroy - a cleanup which performs a partial -/// array destroy where the end pointer is regularly determined and -/// does not need to be loaded from a local. -class RegularPartialArrayDestroy final : public EHScopeStack::Cleanup { - llvm::Value *ArrayBegin; - llvm::Value *ArrayEnd; - QualType ElementType; - CodeGenFunction::Destroyer *Destroyer; - CharUnits ElementAlign; - -public: - RegularPartialArrayDestroy(llvm::Value *arrayBegin, llvm::Value *arrayEnd, - QualType elementType, CharUnits elementAlign, - CodeGenFunction::Destroyer *destroyer) - : ArrayBegin(arrayBegin), ArrayEnd(arrayEnd), ElementType(elementType), - Destroyer(destroyer), ElementAlign(elementAlign) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - emitPartialArrayDestroy(CGF, ArrayBegin, ArrayEnd, ElementType, - ElementAlign, Destroyer); - } -}; - -/// IrregularPartialArrayDestroy - a cleanup which performs a -/// partial array destroy where the end pointer is irregularly -/// determined and must be loaded from a local. -class IrregularPartialArrayDestroy final : public EHScopeStack::Cleanup { - llvm::Value *ArrayBegin; - Address ArrayEndPointer; - QualType ElementType; - CodeGenFunction::Destroyer *Destroyer; - CharUnits ElementAlign; - -public: - IrregularPartialArrayDestroy(llvm::Value *arrayBegin, Address arrayEndPointer, + /// RegularPartialArrayDestroy - a cleanup which performs a partial + /// array destroy where the end pointer is regularly determined and + /// does not need to be loaded from a local. + class RegularPartialArrayDestroy final : public EHScopeStack::Cleanup { + llvm::Value *ArrayBegin; + llvm::Value *ArrayEnd; + QualType ElementType; + CodeGenFunction::Destroyer *Destroyer; + CharUnits ElementAlign; + public: + RegularPartialArrayDestroy(llvm::Value *arrayBegin, llvm::Value *arrayEnd, QualType elementType, CharUnits elementAlign, CodeGenFunction::Destroyer *destroyer) + : ArrayBegin(arrayBegin), ArrayEnd(arrayEnd), + ElementType(elementType), Destroyer(destroyer), + ElementAlign(elementAlign) {} + + void Emit(CodeGenFunction &CGF, Flags flags) override { + emitPartialArrayDestroy(CGF, ArrayBegin, ArrayEnd, + ElementType, ElementAlign, Destroyer); + } + }; + + /// IrregularPartialArrayDestroy - a cleanup which performs a + /// partial array destroy where the end pointer is irregularly + /// determined and must be loaded from a local. + class IrregularPartialArrayDestroy final : public EHScopeStack::Cleanup { + llvm::Value *ArrayBegin; + Address ArrayEndPointer; + QualType ElementType; + CodeGenFunction::Destroyer *Destroyer; + CharUnits ElementAlign; + public: + IrregularPartialArrayDestroy(llvm::Value *arrayBegin, + Address arrayEndPointer, + QualType elementType, + CharUnits elementAlign, + CodeGenFunction::Destroyer *destroyer) : ArrayBegin(arrayBegin), ArrayEndPointer(arrayEndPointer), ElementType(elementType), Destroyer(destroyer), ElementAlign(elementAlign) {} - void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::Value *arrayEnd = CGF.Builder.CreateLoad(ArrayEndPointer); - emitPartialArrayDestroy(CGF, ArrayBegin, arrayEnd, ElementType, - ElementAlign, Destroyer); - } -}; + void Emit(CodeGenFunction &CGF, Flags flags) override { + llvm::Value *arrayEnd = CGF.Builder.CreateLoad(ArrayEndPointer); + emitPartialArrayDestroy(CGF, ArrayBegin, arrayEnd, + ElementType, ElementAlign, Destroyer); + } + }; } // end anonymous namespace /// pushIrregularPartialArrayCleanup - Push an EH cleanup to destroy @@ -2434,9 +2432,10 @@ void CodeGenFunction::pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin, QualType elementType, CharUnits elementAlign, Destroyer *destroyer) { - pushFullExprCleanup<IrregularPartialArrayDestroy>( - EHCleanup, arrayBegin, arrayEndPointer, elementType, elementAlign, - destroyer); + pushFullExprCleanup<IrregularPartialArrayDestroy>(EHCleanup, + arrayBegin, arrayEndPointer, + elementType, elementAlign, + destroyer); } /// pushRegularPartialArrayCleanup - Push an EH cleanup to destroy @@ -2450,16 +2449,18 @@ void CodeGenFunction::pushRegularPartialArrayCleanup(llvm::Value *arrayBegin, QualType elementType, CharUnits elementAlign, Destroyer *destroyer) { - pushFullExprCleanup<RegularPartialArrayDestroy>( - EHCleanup, arrayBegin, arrayEnd, elementType, elementAlign, destroyer); + pushFullExprCleanup<RegularPartialArrayDestroy>(EHCleanup, + arrayBegin, arrayEnd, + elementType, elementAlign, + destroyer); } /// Lazily declare the @llvm.lifetime.start intrinsic. llvm::Function *CodeGenModule::getLLVMLifetimeStartFn() { if (LifetimeStartFn) return LifetimeStartFn; - LifetimeStartFn = llvm::Intrinsic::getDeclaration( - &getModule(), llvm::Intrinsic::lifetime_start, AllocaInt8PtrTy); + LifetimeStartFn = llvm::Intrinsic::getDeclaration(&getModule(), + llvm::Intrinsic::lifetime_start, AllocaInt8PtrTy); return LifetimeStartFn; } @@ -2467,27 +2468,28 @@ llvm::Function *CodeGenModule::getLLVMLifetimeStartFn() { llvm::Function *CodeGenModule::getLLVMLifetimeEndFn() { if (LifetimeEndFn) return LifetimeEndFn; - LifetimeEndFn = llvm::Intrinsic::getDeclaration( - &getModule(), llvm::Intrinsic::lifetime_end, AllocaInt8PtrTy); + LifetimeEndFn = llvm::Intrinsic::getDeclaration(&getModule(), + llvm::Intrinsic::lifetime_end, AllocaInt8PtrTy); return LifetimeEndFn; } namespace { -/// A cleanup to perform a release of an object at the end of a -/// function. This is used to balance out the incoming +1 of a -/// ns_consumed argument when we can't reasonably do that just by -/// not doing the initial retain for a __block argument. -struct ConsumeARCParameter final : EHScopeStack::Cleanup { - ConsumeARCParameter(llvm::Value *param, ARCPreciseLifetime_t precise) + /// A cleanup to perform a release of an object at the end of a + /// function. This is used to balance out the incoming +1 of a + /// ns_consumed argument when we can't reasonably do that just by + /// not doing the initial retain for a __block argument. + struct ConsumeARCParameter final : EHScopeStack::Cleanup { + ConsumeARCParameter(llvm::Value *param, + ARCPreciseLifetime_t precise) : Param(param), Precise(precise) {} - llvm::Value *Param; - ARCPreciseLifetime_t Precise; + llvm::Value *Param; + ARCPreciseLifetime_t Precise; - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitARCRelease(Param, Precise); - } -}; + void Emit(CodeGenFunction &CGF, Flags flags) override { + CGF.EmitARCRelease(Param, Precise); + } + }; } // end anonymous namespace /// Emit an alloca (or GlobalValue depending on target) @@ -2631,18 +2633,18 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, EmitStoreOfScalar(Null, lv, /* isInitialization */ true); EmitARCStoreStrongCall(lv.getAddress(*this), ArgVal, true); DoStore = false; - } else - // Don't use objc_retainBlock for block pointers, because we - // don't want to Block_copy something just because we got it - // as a parameter. + } + else + // Don't use objc_retainBlock for block pointers, because we + // don't want to Block_copy something just because we got it + // as a parameter. ArgVal = EmitARCRetainNonBlock(ArgVal); } } else { // Push the cleanup for a consumed parameter. if (isConsumed) { - ARCPreciseLifetime_t precise = - (D.hasAttr<ObjCPreciseLifetimeAttr>() ? ARCPreciseLifetime - : ARCImpreciseLifetime); + ARCPreciseLifetime_t precise = (D.hasAttr<ObjCPreciseLifetimeAttr>() + ? ARCPreciseLifetime : ARCImpreciseLifetime); EHStack.pushCleanup<ConsumeARCParameter>(getARCCleanupKind(), ArgVal, precise); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits