[clang] Add size filter for stack auto init (PR #74777)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 7 15:04:23 PST 2023
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 <haopliu at google.com>
Date: Thu, 7 Dec 2023 21:25:33 +0000
Subject: [PATCH 1/3] 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 676f1a62b49dd0..5fd097154d0fac 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 c3d5399905a3fd..8325561fc6d23f 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 0eec2b35263762..f92dbd07de20d2 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 a5da0aa2965a00..1f9650e60d5e0a 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 f02f7c841b91f0..669c85c8c7722f 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 ebe8a0520bf0fc..7f947d2de5c6ea 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 <haopliu at google.com>
Date: Thu, 7 Dec 2023 21:30:07 +0000
Subject: [PATCH 2/3] 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 00000000000000..1f6c2b143d3978
--- /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 <haopliu at google.com>
Date: Thu, 7 Dec 2023 22:54:22 +0000
Subject: [PATCH 3/3] 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 1f9650e60d5e0a..d64ced5382b4b8 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);
}
More information about the cfe-commits
mailing list