]> granicus.if.org Git - clang/commitdiff
Under a compiler flag, -freset-local-blocks,
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 28 Jun 2011 23:51:26 +0000 (23:51 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 28 Jun 2011 23:51:26 +0000 (23:51 +0000)
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

include/clang/Basic/LangOptions.h
include/clang/Driver/CC1Options.td
include/clang/Driver/Options.td
lib/CodeGen/CGBlocks.cpp
lib/Driver/Tools.cpp
lib/Frontend/CompilerInvocation.cpp
test/CodeGen/reset-local-block.c [new file with mode: 0644]

index 7eda0aa3fdcde7ba5a126b27d9485542547935c9..e99d8722098a320401bf6320126dd2ab0fb97e64 100644 (file)
@@ -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;
index 653f346b9e2594c4391319b77202baee97d3f7d1..6b580670a6e5f730c03408e6ee8b4e8e974e5b22 100644 (file)
@@ -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">;
index c6965484487366d4760523252779ae4a609923ba..3806240ae1481eb87a7ab52fe706949d00ef8e7c 100644 (file)
@@ -259,6 +259,7 @@ def fastf : Flag<"-fastf">, Group<f_Group>;
 def fast : Flag<"-fast">, Group<f_Group>;
 def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group<f_Group>;
 def fblocks : Flag<"-fblocks">, Group<f_Group>;
+def freset_local_blocks : Flag<"-freset-local-blocks">, Group<f_Group>;
 def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>;
 def fborland_extensions : Flag<"-fborland-extensions">, Group<f_Group>;
 def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>;
index a0a8d667df622e513202d154c156b553070f6b00..20b5c9bed0b5574a410d8b73f58ad4329e74840d 100644 (file)
 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<CallMemsetLocalBlockObject>(NormalCleanup, blockAddr, 
+                                                    blockInfo.BlockSize);
 
   return result;
 }
index 41be873b35ff9aa31099089389c4d983d2b9681c..d384c2b739682af0ee80b09fe851ee91f52b84fc 100644 (file)
@@ -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,
index 12e51a61e1f08222b8c86a23f43b4997ae7195fa..f2ca212b3ad99347ac352091e154dd9f9a0460e6 100644 (file)
@@ -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 (file)
index 0000000..01b8828
--- /dev/null
@@ -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)