[cfe-commits] r113330 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGCXXABI.h lib/CodeGen/CGDecl.cpp lib/CodeGen/CGDeclCXX.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/Mangle.cpp lib/CodeGen/Mangle.h lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGenCXX/arm.cpp test/CodeGenCXX/static-init.cpp test/CodeGenCXX/threadsafe-statics-exceptions.cpp
John McCall
rjmccall at apple.com
Tue Sep 7 18:44:27 PDT 2010
Author: rjmccall
Date: Tue Sep 7 20:44:27 2010
New Revision: 113330
URL: http://llvm.org/viewvc/llvm-project?rev=113330&view=rev
Log:
Implement ARM static local initialization guards, which are more compact than
Itanium guards and use a slightly different compiled-in API.
Modified:
cfe/trunk/lib/CodeGen/CGCXX.cpp
cfe/trunk/lib/CodeGen/CGCXXABI.h
cfe/trunk/lib/CodeGen/CGDecl.cpp
cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
cfe/trunk/lib/CodeGen/Mangle.cpp
cfe/trunk/lib/CodeGen/Mangle.h
cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
cfe/trunk/test/CodeGenCXX/arm.cpp
cfe/trunk/test/CodeGenCXX/static-init.cpp
cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Tue Sep 7 20:44:27 2010
@@ -321,7 +321,7 @@
/// Implementation for CGCXXABI. Possibly this should be moved into
/// the incomplete ABI implementations?
-CGCXXABI::~CGCXXABI() {}
+void CGCXXABI::_anchor() {}
static void ErrorUnsupportedABI(CodeGenFunction &CGF,
llvm::StringRef S) {
@@ -469,3 +469,9 @@
AllocPtr = llvm::Constant::getNullValue(CGF.Builder.getInt8PtrTy());
CookieSize = CharUnits::Zero();
}
+
+void CGCXXABI::EmitStaticLocalInit(CodeGenFunction &CGF,
+ const VarDecl &D,
+ llvm::GlobalVariable *GV) {
+ ErrorUnsupportedABI(CGF, "static local variable initialization");
+}
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Tue Sep 7 20:44:27 2010
@@ -69,9 +69,11 @@
ASTContext &getContext() const { return CGM.getContext(); }
+ virtual void _anchor();
+
public:
- virtual ~CGCXXABI();
+ virtual ~CGCXXABI() {}
/// Gets the mangle context.
virtual MangleContext &getMangleContext() = 0;
@@ -217,6 +219,14 @@
QualType ElementType, llvm::Value *&NumElements,
llvm::Value *&AllocPtr, CharUnits &CookieSize);
+ /*************************** Static local guards ****************************/
+
+ /// Emits the initializer and destructor setup for the given static
+ /// local variable, given that it's reachable and couldn't be
+ /// emitted as a constant.
+ virtual void EmitStaticLocalInit(CodeGenFunction &CGF, const VarDecl &D,
+ llvm::GlobalVariable *DeclPtr);
+
};
/// Creates an instance of a C++ ABI class.
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Tue Sep 7 20:44:27 2010
@@ -189,12 +189,12 @@
if (!Init) {
if (!getContext().getLangOptions().CPlusPlus)
CGM.ErrorUnsupported(D.getInit(), "constant l-value expression");
- else {
+ else if (Builder.GetInsertBlock()) {
// Since we have a static initializer, this global variable can't
// be constant.
GV->setConstant(false);
-
- EmitStaticCXXBlockVarDeclInit(D, GV);
+
+ EmitCXXStaticLocalInit(D, GV);
}
return GV;
}
Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Tue Sep 7 20:44:27 2010
@@ -42,6 +42,8 @@
}
}
+/// 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 @@
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 @@
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.
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Sep 7 20:44:27 2010
@@ -1565,11 +1565,6 @@
llvm::GlobalVariable *GV);
- /// EmitStaticCXXBlockVarDeclInit - Create the initializer for a C++ runtime
- /// initialized static block var decl.
- void EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
- llvm::GlobalVariable *GV);
-
/// EmitCXXGlobalVarDeclInit - Create the initializer for a C++
/// variable with global storage.
void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr);
@@ -1579,6 +1574,8 @@
void EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
llvm::Constant *DeclPtr);
+ void EmitCXXStaticLocalInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr);
+
/// GenerateCXXGlobalInitFunc - Generates code for initializing global
/// variables.
void GenerateCXXGlobalInitFunc(llvm::Function *Fn,
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Sep 7 20:44:27 2010
@@ -119,6 +119,9 @@
void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
QualType ElementType, llvm::Value *&NumElements,
llvm::Value *&AllocPtr, CharUnits &CookieSize);
+
+ void EmitStaticLocalInit(CodeGenFunction &CGF, const VarDecl &D,
+ llvm::GlobalVariable *DeclPtr);
};
class ARMCXXABI : public ItaniumCXXABI {
@@ -1021,3 +1024,159 @@
NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
}
+/*********************** Static local initialization **************************/
+
+static llvm::Constant *getGuardAcquireFn(CodeGenModule &CGM,
+ const llvm::PointerType *GuardPtrTy) {
+ // int __cxa_guard_acquire(__guard *guard_object);
+
+ std::vector<const llvm::Type*> Args(1, GuardPtrTy);
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy),
+ Args, /*isVarArg=*/false);
+
+ return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire");
+}
+
+static llvm::Constant *getGuardReleaseFn(CodeGenModule &CGM,
+ const llvm::PointerType *GuardPtrTy) {
+ // void __cxa_guard_release(__guard *guard_object);
+
+ std::vector<const llvm::Type*> Args(1, GuardPtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
+ Args, /*isVarArg=*/false);
+
+ return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release");
+}
+
+static llvm::Constant *getGuardAbortFn(CodeGenModule &CGM,
+ const llvm::PointerType *GuardPtrTy) {
+ // void __cxa_guard_abort(__guard *guard_object);
+
+ std::vector<const llvm::Type*> Args(1, GuardPtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
+ Args, /*isVarArg=*/false);
+
+ return 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) {
+ CGF.Builder.CreateCall(getGuardAbortFn(CGF.CGM, Guard->getType()), Guard)
+ ->setDoesNotThrow();
+ }
+ };
+}
+
+/// The ARM code here follows the Itanium code closely enough that we
+/// just special-case it at particular places.
+void ItaniumCXXABI::EmitStaticLocalInit(CodeGenFunction &CGF,
+ const VarDecl &D,
+ llvm::GlobalVariable *GV) {
+ CGBuilderTy &Builder = CGF.Builder;
+ bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
+
+ // Guard variables are 64 bits in the generic ABI and 32 bits on ARM.
+ const llvm::IntegerType *GuardTy
+ = (IsARM ? Builder.getInt32Ty() : Builder.getInt64Ty());
+ const llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo();
+
+ // Create the guard variable.
+ llvm::SmallString<256> GuardVName;
+ getMangleContext().mangleItaniumGuardVariable(&D, GuardVName);
+ llvm::GlobalVariable *GuardVariable =
+ new llvm::GlobalVariable(CGM.getModule(), GuardTy,
+ false, GV->getLinkage(),
+ llvm::ConstantInt::get(GuardTy, 0),
+ GuardVName.str());
+
+ // Test whether the variable has completed initialization.
+ llvm::Value *IsInitialized;
+
+ // ARM C++ ABI 3.2.3.1:
+ // To support the potential use of initialization guard variables
+ // as semaphores that are the target of ARM SWP and LDREX/STREX
+ // synchronizing instructions we define a static initialization
+ // guard variable to be a 4-byte aligned, 4- byte word with the
+ // following inline access protocol.
+ // #define INITIALIZED 1
+ // if ((obj_guard & INITIALIZED) != INITIALIZED) {
+ // if (__cxa_guard_acquire(&obj_guard))
+ // ...
+ // }
+ if (IsARM) {
+ llvm::Value *V = Builder.CreateLoad(GuardVariable);
+ V = Builder.CreateAnd(V, Builder.getInt32(1));
+ IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
+
+ // Itanium C++ ABI 3.3.2:
+ // The following is pseudo-code showing how these functions can be used:
+ // if (obj_guard.first_byte == 0) {
+ // if ( __cxa_guard_acquire (&obj_guard) ) {
+ // try {
+ // ... initialize the object ...;
+ // } catch (...) {
+ // __cxa_guard_abort (&obj_guard);
+ // throw;
+ // }
+ // ... queue object destructor with __cxa_atexit() ...;
+ // __cxa_guard_release (&obj_guard);
+ // }
+ // }
+ } else {
+ // Load the first byte of the guard variable.
+ const llvm::Type *PtrTy = Builder.getInt8PtrTy();
+ llvm::Value *V =
+ Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
+
+ IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
+ }
+
+ llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
+ llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
+
+ // Check if the first byte of the guard variable is zero.
+ Builder.CreateCondBr(IsInitialized, InitCheckBlock, EndBlock);
+
+ CGF.EmitBlock(InitCheckBlock);
+
+ // Variables used when coping with thread-safe statics and exceptions.
+ if (ThreadsafeStatics) {
+ // Call __cxa_guard_acquire.
+ llvm::Value *V
+ = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable);
+
+ llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
+
+ Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
+ InitBlock, EndBlock);
+
+ // Call __cxa_guard_abort along the exceptional edge.
+ CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable);
+
+ CGF.EmitBlock(InitBlock);
+ }
+
+ // Emit the initializer and add a global destructor if appropriate.
+ CGF.EmitCXXGlobalVarDeclInit(D, GV);
+
+ if (ThreadsafeStatics) {
+ // Pop the guard-abort cleanup if we pushed one.
+ CGF.PopCleanupBlock();
+
+ // Call __cxa_guard_release. This cannot throw.
+ Builder.CreateCall(getGuardReleaseFn(CGM, GuardPtrTy), GuardVariable);
+ } else {
+ Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable);
+ }
+
+ CGF.EmitBlock(EndBlock);
+}
Modified: cfe/trunk/lib/CodeGen/Mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
+++ cfe/trunk/lib/CodeGen/Mangle.cpp Tue Sep 7 20:44:27 2010
@@ -2451,8 +2451,8 @@
/// mangleGuardVariable - Returns the mangled name for a guard variable
/// for the passed in VarDecl.
-void MangleContext::mangleGuardVariable(const VarDecl *D,
- llvm::SmallVectorImpl<char> &Res) {
+void MangleContext::mangleItaniumGuardVariable(const VarDecl *D,
+ llvm::SmallVectorImpl<char> &Res) {
// <special-name> ::= GV <object name> # Guard variable for one-time
// # initialization
CXXNameMangler Mangler(*this, Res);
Modified: cfe/trunk/lib/CodeGen/Mangle.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.h?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.h (original)
+++ cfe/trunk/lib/CodeGen/Mangle.h Tue Sep 7 20:44:27 2010
@@ -119,8 +119,6 @@
virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
llvm::SmallVectorImpl<char> &);
- virtual void mangleGuardVariable(const VarDecl *D,
- llvm::SmallVectorImpl<char> &);
virtual void mangleReferenceTemporary(const VarDecl *D,
llvm::SmallVectorImpl<char> &);
virtual void mangleCXXVTable(const CXXRecordDecl *RD,
@@ -139,6 +137,10 @@
void mangleBlock(GlobalDecl GD,
const BlockDecl *BD, llvm::SmallVectorImpl<char> &);
+ // This is pretty lame.
+ void mangleItaniumGuardVariable(const VarDecl *D,
+ llvm::SmallVectorImpl<char> &);
+
void mangleInitDiscriminator() {
Discriminator = 0;
}
Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Sep 7 20:44:27 2010
@@ -91,8 +91,6 @@
virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
llvm::SmallVectorImpl<char> &);
- virtual void mangleGuardVariable(const VarDecl *D,
- llvm::SmallVectorImpl<char> &);
virtual void mangleCXXVTable(const CXXRecordDecl *RD,
llvm::SmallVectorImpl<char> &);
virtual void mangleCXXVTT(const CXXRecordDecl *RD,
@@ -1175,10 +1173,6 @@
llvm::SmallVectorImpl<char> &) {
assert(false && "Can't yet mangle destructor thunks!");
}
-void MicrosoftMangleContext::mangleGuardVariable(const VarDecl *D,
- llvm::SmallVectorImpl<char> &) {
- assert(false && "Can't yet mangle guard variables!");
-}
void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
llvm::SmallVectorImpl<char> &) {
assert(false && "Can't yet mangle virtual tables!");
Modified: cfe/trunk/test/CodeGenCXX/arm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/arm.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/arm.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/arm.cpp Tue Sep 7 20:44:27 2010
@@ -1,5 +1,10 @@
// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s
+// CHECK: @_ZZN5test74testEvE1x = internal global i32 0, align 4
+// CHECK: @_ZGVZN5test74testEvE1x = internal global i32 0
+// CHECK: @_ZZN5test84testEvE1x = internal global [[TEST8A:.*]] zeroinitializer, align 1
+// CHECK: @_ZGVZN5test84testEvE1x = internal global i32 0
+
typedef typeof(sizeof(int)) size_t;
class foo {
@@ -277,6 +282,76 @@
}
}
+namespace test7 {
+ int foo();
+
+ // Static and guard tested at top of file
+
+ // CHECK: define void @_ZN5test74testEv()
+ void test() {
+ // CHECK: [[T0:%.*]] = load i32* @_ZGVZN5test74testEvE1x
+ // CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1
+ // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
+ // CHECK-NEXT: br i1 [[T2]]
+ // -> fallthrough, end
+ // CHECK: [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test74testEvE1x)
+ // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0
+ // CHECK-NEXT: br i1 [[T4]]
+ // -> fallthrough, end
+ // CHECK: [[INIT:%.*]] = invoke i32 @_ZN5test73fooEv()
+ // CHECK: store i32 [[INIT]], i32* @_ZZN5test74testEvE1x, align 4
+ // CHECK-NEXT: call void @__cxa_guard_release(i32* @_ZGVZN5test74testEvE1x)
+ // CHECK-NEXT: br label
+ // -> end
+ // end:
+ // CHECK: ret void
+ static int x = foo();
+
+ // CHECK: call i8* @llvm.eh.exception()
+ // CHECK: call void @__cxa_guard_abort(i32* @_ZGVZN5test74testEvE1x)
+ // CHECK: call void @_Unwind_Resume_or_Rethrow
+ }
+}
+
+namespace test8 {
+ struct A {
+ A();
+ ~A();
+ };
+
+ // Static and guard tested at top of file
+
+ // CHECK: define void @_ZN5test84testEv()
+ void test() {
+ // CHECK: [[T0:%.*]] = load i32* @_ZGVZN5test84testEvE1x
+ // CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1
+ // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
+ // CHECK-NEXT: br i1 [[T2]]
+ // -> fallthrough, end
+ // CHECK: [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test84testEvE1x)
+ // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0
+ // CHECK-NEXT: br i1 [[T4]]
+ // -> fallthrough, end
+ // CHECK: [[INIT:%.*]] = invoke [[TEST8A]]* @_ZN5test81AC1Ev([[TEST8A]]* @_ZZN5test84testEvE1x)
+
+ // FIXME: Here we register a global destructor that
+ // unconditionally calls the destructor. That's what we've always
+ // done for -fno-use-cxa-atexit here, but that's really not
+ // semantically correct at all.
+
+ // CHECK: call void @__cxa_guard_release(i32* @_ZGVZN5test84testEvE1x)
+ // CHECK-NEXT: br label
+ // -> end
+ // end:
+ // CHECK: ret void
+ static A x;
+
+ // CHECK: call i8* @llvm.eh.exception()
+ // CHECK: call void @__cxa_guard_abort(i32* @_ZGVZN5test84testEvE1x)
+ // CHECK: call void @_Unwind_Resume_or_Rethrow
+ }
+}
+
// CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
// CHECK: call [[C]]* @_ZN5test21CD1Ev(
// CHECK: ret [[C]]* undef
Modified: cfe/trunk/test/CodeGenCXX/static-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/static-init.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/static-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/static-init.cpp Tue Sep 7 20:44:27 2010
@@ -14,8 +14,8 @@
void f() {
// CHECK: call i32 @__cxa_guard_acquire
// CHECK: call void @_ZN1AC1Ev
- // CHECK: call void @__cxa_guard_release
// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @_ZZ1fvE1a, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
+ // CHECK: call void @__cxa_guard_release
static A a;
}
Modified: cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp Tue Sep 7 20:44:27 2010
@@ -11,8 +11,8 @@
void f() {
// CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZ1fvE1x)
// CHECK: invoke void @_ZN1XC1Ev
- // CHECK: call void @__cxa_guard_release(i64* @_ZGVZ1fvE1x)
- // CHECK-NEXT: call i32 @__cxa_atexit
+ // CHECK: call i32 @__cxa_atexit
+ // CHECK-NEXT: call void @__cxa_guard_release(i64* @_ZGVZ1fvE1x)
// CHECK: br
static X x;
More information about the cfe-commits
mailing list