diff options
author | John McCall <rjmccall@apple.com> | 2010-09-08 01:44:27 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-09-08 01:44:27 +0000 |
commit | 5cd91b513455fd7753e8815b54f0a49bbca6602d (patch) | |
tree | e2aec9abdce6a7183211e487e100a98b172c14c4 /lib/CodeGen/CGDeclCXX.cpp | |
parent | 607a1788d9529c8e8494ac528764aa2c678a1a97 (diff) |
Implement ARM static local initialization guards, which are more compact than
Itanium guards and use a slightly different compiled-in API.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113330 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGDeclCXX.cpp')
-rw-r--r-- | lib/CodeGen/CGDeclCXX.cpp | 144 |
1 files changed, 7 insertions, 137 deletions
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index e2f197522b..565c865c34 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -42,6 +42,8 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, } } +/// Emit code to cause the destruction of the given variable with +/// static storage duration. static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D, llvm::Constant *DeclPtr) { CodeGenModule &CGM = CGF.CGM; @@ -138,6 +140,11 @@ CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args)); } +void CodeGenFunction::EmitCXXStaticLocalInit(const VarDecl &D, + llvm::GlobalVariable *DeclPtr) { + CGM.getCXXABI().EmitStaticLocalInit(*this, D, DeclPtr); +} + static llvm::Function * CreateGlobalInitOrDestructFunction(CodeGenModule &CGM, const llvm::FunctionType *FTy, @@ -283,143 +290,6 @@ void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, FinishFunction(); } -static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) { - // int __cxa_guard_acquire(__int64_t *guard_object); - - const llvm::Type *Int64PtrTy = - llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); - - std::vector<const llvm::Type*> Args(1, Int64PtrTy); - - const llvm::FunctionType *FTy = - llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy), - Args, /*isVarArg=*/false); - - return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire"); -} - -static llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) { - // void __cxa_guard_release(__int64_t *guard_object); - - const llvm::Type *Int64PtrTy = - llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); - - std::vector<const llvm::Type*> Args(1, Int64PtrTy); - - const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), - Args, /*isVarArg=*/false); - - return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release"); -} - -static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) { - // void __cxa_guard_abort(__int64_t *guard_object); - - const llvm::Type *Int64PtrTy = - llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); - - std::vector<const llvm::Type*> Args(1, Int64PtrTy); - - const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), - Args, /*isVarArg=*/false); - - return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort"); -} - -namespace { - struct CallGuardAbort : EHScopeStack::Cleanup { - llvm::GlobalVariable *Guard; - CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {} - - void Emit(CodeGenFunction &CGF, bool IsForEH) { - // It shouldn't be possible for this to throw, but if it can, - // this should allow for the possibility of an invoke. - CGF.Builder.CreateCall(getGuardAbortFn(CGF), Guard) - ->setDoesNotThrow(); - } - }; -} - -void -CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, - llvm::GlobalVariable *GV) { - // Bail out early if this initializer isn't reachable. - if (!Builder.GetInsertBlock()) return; - - bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics; - - llvm::SmallString<256> GuardVName; - CGM.getCXXABI().getMangleContext().mangleGuardVariable(&D, GuardVName); - - // Create the guard variable. - llvm::GlobalVariable *GuardVariable = - new llvm::GlobalVariable(CGM.getModule(), Int64Ty, - false, GV->getLinkage(), - llvm::Constant::getNullValue(Int64Ty), - GuardVName.str()); - - // Load the first byte of the guard variable. - const llvm::Type *PtrTy - = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); - llvm::Value *V = - Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp"); - - llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check"); - llvm::BasicBlock *EndBlock = createBasicBlock("init.end"); - - // Check if the first byte of the guard variable is zero. - Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"), - InitCheckBlock, EndBlock); - - EmitBlock(InitCheckBlock); - - // Variables used when coping with thread-safe statics and exceptions. - if (ThreadsafeStatics) { - // Call __cxa_guard_acquire. - V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable); - - llvm::BasicBlock *InitBlock = createBasicBlock("init"); - - Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), - InitBlock, EndBlock); - - // Call __cxa_guard_abort along the exceptional edge. - if (Exceptions) - EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable); - - EmitBlock(InitBlock); - } - - if (D.getType()->isReferenceType()) { - unsigned Alignment = getContext().getDeclAlign(&D).getQuantity(); - QualType T = D.getType(); - RValue RV = EmitReferenceBindingToExpr(D.getInit(), &D); - EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, Alignment, T); - } else - EmitDeclInit(*this, D, GV); - - if (ThreadsafeStatics) { - // Pop the guard-abort cleanup if we pushed one. - if (Exceptions) - PopCleanupBlock(); - - // Call __cxa_guard_release. This cannot throw. - Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable); - } else { - llvm::Value *One = - llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1); - Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy)); - } - - // Register the call to the destructor. - if (!D.getType()->isReferenceType()) - EmitDeclDestroy(*this, D, GV); - - EmitBlock(EndBlock); -} - /// GenerateCXXAggrDestructorHelper - Generates a helper function which when /// invoked, calls the default destructor on array elements in reverse order of /// construction. |