From: John McCall Date: Wed, 21 Jul 2010 06:13:08 +0000 (+0000) Subject: Switch some random local-decl cleanups over to using lazy cleanups. Turn on X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d87150999833d756269d84ca6e4127dc99fdcf63;p=clang Switch some random local-decl cleanups over to using lazy cleanups. Turn on the block-release unwind cleanup: we're never going to test it if we don't turn it on. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108992 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 8d0d338474..da2c03bc99 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -440,6 +440,57 @@ namespace { }; } +namespace { + struct CallStackRestore : EHScopeStack::LazyCleanup { + llvm::Value *Stack; + CallStackRestore(llvm::Value *Stack) : Stack(Stack) {} + void Emit(CodeGenFunction &CGF, bool IsForEH) { + llvm::Value *V = CGF.Builder.CreateLoad(Stack, "tmp"); + llvm::Value *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stackrestore); + CGF.Builder.CreateCall(F, V); + } + }; + + struct CallCleanupFunction : EHScopeStack::LazyCleanup { + llvm::Constant *CleanupFn; + const CGFunctionInfo &FnInfo; + llvm::Value *Addr; + const VarDecl &Var; + + CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info, + llvm::Value *Addr, const VarDecl *Var) + : CleanupFn(CleanupFn), FnInfo(*Info), Addr(Addr), Var(*Var) {} + + void Emit(CodeGenFunction &CGF, bool IsForEH) { + // 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.push_back(std::make_pair(RValue::get(Arg), + CGF.getContext().getPointerType(Var.getType()))); + CGF.EmitCall(FnInfo, CleanupFn, ReturnValueSlot(), Args); + } + }; + + struct CallBlockRelease : EHScopeStack::LazyCleanup { + llvm::Value *Addr; + CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {} + + void Emit(CodeGenFunction &CGF, bool IsForEH) { + llvm::Value *V = CGF.Builder.CreateStructGEP(Addr, 1, "forwarding"); + V = CGF.Builder.CreateLoad(V); + CGF.BuildBlockRelease(V); + } + }; +} + /// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a /// variable declaration with auto, register, or no storage class specifier. /// These turn into simple stack objects, or GlobalValues depending on target. @@ -540,14 +591,8 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D, DidCallStackSave = true; - { - // Push a cleanup block and restore the stack there. - CleanupBlock scope(*this, NormalCleanup); - - V = Builder.CreateLoad(Stack, "tmp"); - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore); - Builder.CreateCall(F, V); - } + // Push a cleanup block and restore the stack there. + EHStack.pushLazyCleanup(NormalCleanup, Stack); } // Get the element type. @@ -755,52 +800,12 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D, assert(F && "Could not find function!"); const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD); - - // 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 = Info.arg_begin()->type; - - CleanupBlock CleanupScope(*this, NormalCleanup); - - // Normal cleanup. - CallArgList Args; - Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr, - ConvertType(ArgTy))), - getContext().getPointerType(D.getType()))); - EmitCall(Info, F, ReturnValueSlot(), Args); - - // EH cleanup. - if (Exceptions) { - CleanupScope.beginEHCleanup(); - - CallArgList Args; - Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr, - ConvertType(ArgTy))), - getContext().getPointerType(D.getType()))); - EmitCall(Info, F, ReturnValueSlot(), Args); - } + EHStack.pushLazyCleanup(NormalAndEHCleanup, + F, &Info, DeclPtr, &D); } - if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) { - CleanupBlock CleanupScope(*this, NormalCleanup); - - llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding"); - V = Builder.CreateLoad(V); - BuildBlockRelease(V); - - // FIXME: Turn this on and audit the codegen - if (0 && Exceptions) { - CleanupScope.beginEHCleanup(); - - llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding"); - V = Builder.CreateLoad(V); - BuildBlockRelease(V); - } - } + if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) + EHStack.pushLazyCleanup(NormalAndEHCleanup, DeclPtr); } /// Emit an alloca (or GlobalValue depending on target) diff --git a/test/CodeGen/block-decl-merging.c b/test/CodeGen/block-decl-merging.c index 5a3d95b827..1e7a9f4e92 100644 --- a/test/CodeGen/block-decl-merging.c +++ b/test/CodeGen/block-decl-merging.c @@ -5,10 +5,10 @@ extern void * _NSConcreteStackBlock[32] __attribute__((weak_import)); // CHECK: @_NSConcreteStackBlock = extern_weak global extern void * _NSConcreteGlobalBlock[32] __attribute__((weak_import)); -// CHECK: declare extern_weak void @_Block_object_dispose extern void _Block_object_dispose(const void *, const int) __attribute__((weak_import)); // CHECK: declare extern_weak void @_Block_object_assign extern void _Block_object_assign(void *, const void *, const int) __attribute__((weak_import)); +// CHECK: declare extern_weak void @_Block_object_dispose void *x = ^(){};