From: Fariborz Jahanian Date: Tue, 28 Jun 2011 23:51:26 +0000 (+0000) Subject: Under a compiler flag, -freset-local-blocks, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1077e420b89c9541396135157f22a1eff6062edf;p=clang Under a compiler flag, -freset-local-blocks, wipe out stack blocks when they go out of scope. // rdar://9227352 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134045 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 7eda0aa3fd..e99d872209 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -72,6 +72,7 @@ public: unsigned POSIXThreads : 1; // Compiling with POSIX thread support // (-pthread) unsigned Blocks : 1; // block extension to C + unsigned ResetLocalBlocks : 1; // reset local blocks going out of scope unsigned EmitAllDecls : 1; // Emit all declarations, even if // they are unused. unsigned MathErrno : 1; // Math functions must respect errno @@ -198,7 +199,7 @@ public: ThreadsafeStatics = 1; POSIXThreads = 0; - Blocks = 0; + Blocks = ResetLocalBlocks = 0; EmitAllDecls = 0; MathErrno = 1; SignedOverflowBehavior = SOB_Undefined; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 653f346b9e..6b580670a6 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -444,6 +444,8 @@ def femit_all_decls : Flag<"-femit-all-decls">, HelpText<"Emit all declarations, even if unused">; def fblocks : Flag<"-fblocks">, HelpText<"enable the 'blocks' language feature">; +def freset_local_blocks : Flag<"-freset-local-blocks">, + HelpText<"reset local blocks when they go out of scope">; def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; def fexceptions : Flag<"-fexceptions">, HelpText<"Enable support for exception handling">; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index c696548448..3806240ae1 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -259,6 +259,7 @@ def fastf : Flag<"-fastf">, Group; def fast : Flag<"-fast">, Group; def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group; def fblocks : Flag<"-fblocks">, Group; +def freset_local_blocks : Flag<"-freset-local-blocks">, Group; def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group; def fborland_extensions : Flag<"-fborland-extensions">, Group; def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group; diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index a0a8d667df..20b5c9bed0 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -25,6 +25,22 @@ using namespace clang; using namespace CodeGen; +struct CallMemsetLocalBlockObject : EHScopeStack::Cleanup { + llvm::AllocaInst *BlockAddr; + CharUnits BlockSize; + + CallMemsetLocalBlockObject(llvm::AllocaInst *blockAddr, + CharUnits blocSize) + : BlockAddr(blockAddr), BlockSize(blocSize) {} + + void Emit(CodeGenFunction &CGF, bool isForEH) { + CGF.Builder.CreateMemSet(BlockAddr, + llvm::ConstantInt::get(CGF.Int8Ty, 0xCD), + BlockSize.getQuantity(), + BlockAddr->getAlignment()); + } +}; + CGBlockInfo::CGBlockInfo(const BlockExpr *blockExpr, const char *N) : Name(N), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), HasCXXObject(false), UsesStret(false), StructureType(0), Block(blockExpr) { @@ -649,6 +665,9 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { llvm::Value *result = Builder.CreateBitCast(blockAddr, ConvertType(blockInfo.getBlockExpr()->getType())); + if (getLangOptions().ResetLocalBlocks) + EHStack.pushCleanup(NormalCleanup, blockAddr, + blockInfo.BlockSize); return result; } diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 41be873b35..d384c2b739 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1709,6 +1709,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, !Args.hasArg(options::OPT_fno_blocks))) { CmdArgs.push_back("-fblocks"); } + if (Args.hasArg(options::OPT_freset_local_blocks)) + CmdArgs.push_back("-freset-local-blocks"); // -faccess-control is default. if (Args.hasFlag(options::OPT_fno_access_control, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 12e51a61e1..f2ca212b3a 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -638,6 +638,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-pthread"); if (Opts.Blocks) Res.push_back("-fblocks"); + if (Opts.ResetLocalBlocks) + Res.push_back("-freset-local-blocks"); if (Opts.EmitAllDecls) Res.push_back("-femit-all-decls"); if (Opts.MathErrno) @@ -1612,6 +1614,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.RTTI = !Args.hasArg(OPT_fno_rtti); Opts.Blocks = Args.hasArg(OPT_fblocks); + Opts.ResetLocalBlocks = Args.hasArg(OPT_freset_local_blocks); Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char); Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar); Opts.ShortEnums = Args.hasArg(OPT_fshort_enums); diff --git a/test/CodeGen/reset-local-block.c b/test/CodeGen/reset-local-block.c new file mode 100644 index 0000000000..01b8828a82 --- /dev/null +++ b/test/CodeGen/reset-local-block.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -freset-local-blocks -o - %s | FileCheck %s +// rdar://9227352 + +typedef int (^BLOCK)(); + +BLOCK FUNC() { + int i; + double d; + BLOCK block = ^{ return i + (int)d; }; + if (!block) + block = ^{ return i; }; + return block; +} + +//CHECK: call void @llvm.memset{{.*}}, i8 -51, i64 36, i32 8, i1 false) +//CHECK: call void @llvm.memset{{.*}}, i8 -51, i64 44, i32 8, i1 false)