aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGDeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGDeclCXX.cpp')
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp194
1 files changed, 40 insertions, 154 deletions
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index e2f197522b26..e295267896eb 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGObjCRuntime.h"
#include "CGCXXABI.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/Intrinsics.h"
@@ -34,14 +35,24 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
unsigned Alignment = Context.getDeclAlign(&D).getQuantity();
if (!CGF.hasAggregateLLVMType(T)) {
llvm::Value *V = CGF.EmitScalarExpr(Init);
- CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T);
+ CodeGenModule &CGM = CGF.CGM;
+ Qualifiers::GC GCAttr = CGM.getContext().getObjCGCAttrKind(T);
+ if (GCAttr == Qualifiers::Strong)
+ CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, V, DeclPtr,
+ D.isThreadSpecified());
+ else if (GCAttr == Qualifiers::Weak)
+ CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, V, DeclPtr);
+ else
+ CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T);
} else if (T->isAnyComplexType()) {
CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
} else {
- CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
+ CGF.EmitAggExpr(Init, AggValueSlot::forAddr(DeclPtr, isVolatile, true));
}
}
+/// 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;
@@ -106,15 +117,13 @@ CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
return;
}
- const llvm::Type *Int8PtrTy =
- llvm::Type::getInt8Ty(VMContext)->getPointerTo();
-
std::vector<const llvm::Type *> Params;
Params.push_back(Int8PtrTy);
// Get the destructor function type
const llvm::Type *DtorFnTy =
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
+ llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()),
+ Params, false);
DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
Params.clear();
@@ -138,6 +147,11 @@ CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
}
+void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
+ llvm::GlobalVariable *DeclPtr) {
+ CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr);
+}
+
static llvm::Function *
CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
const llvm::FunctionType *FTy,
@@ -145,20 +159,22 @@ CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
llvm::Function *Fn =
llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
Name, &CGM.getModule());
+ if (!CGM.getContext().getLangOptions().AppleKext) {
+ // Set the section if needed.
+ if (const char *Section =
+ CGM.getContext().Target.getStaticInitSectionSpecifier())
+ Fn->setSection(Section);
+ }
- // Set the section if needed.
- if (const char *Section =
- CGM.getContext().Target.getStaticInitSectionSpecifier())
- Fn->setSection(Section);
-
- if (!CGM.getLangOptions().Exceptions)
+ if (!CGM.getLangOptions().areExceptionsEnabled())
Fn->setDoesNotThrow();
return Fn;
}
void
-CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
+CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
+ llvm::GlobalVariable *Addr) {
const llvm::FunctionType *FTy
= llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
false);
@@ -167,7 +183,7 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
llvm::Function *Fn =
CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");
- CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D);
+ CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr);
if (D->hasAttr<InitPriorityAttr>()) {
unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
@@ -240,13 +256,20 @@ void CodeGenModule::EmitCXXGlobalDtorFunc() {
AddGlobalDtor(Fn);
}
+/// Emit the code necessary to initialize the given global variable.
void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
- const VarDecl *D) {
+ const VarDecl *D,
+ llvm::GlobalVariable *Addr) {
StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
SourceLocation());
- llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
- EmitCXXGlobalVarDeclInit(*D, DeclPtr);
+ // Use guarded initialization if the global variable is weak due to
+ // being a class template's static data member.
+ if (Addr->hasWeakLinkage() && D->getInstantiatedFromStaticDataMember()) {
+ EmitCXXGuardedInit(*D, Addr);
+ } else {
+ EmitCXXGlobalVarDeclInit(*D, Addr);
+ }
FinishFunction();
}
@@ -283,143 +306,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.