From 611ba3ea3300b71eb95dc4e45f20eee5dddd32e1 Mon Sep 17 00:00:00 2001
From: dim <dim@FreeBSD.org>
Date: Sun, 17 Jul 2011 15:40:56 +0000
Subject: Vendor import of clang trunk r135360:
 http://llvm.org/svn/llvm-project/cfe/trunk@135360

---
 lib/CodeGen/ItaniumCXXABI.cpp | 123 ++++++++++++++++++++++++++++++------------
 1 file changed, 88 insertions(+), 35 deletions(-)

(limited to 'lib/CodeGen/ItaniumCXXABI.cpp')

diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 12ef9bd..0c86080f 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -24,6 +24,7 @@
 #include "CodeGenModule.h"
 #include <clang/AST/Mangle.h>
 #include <clang/AST/Type.h>
+#include <llvm/Intrinsics.h>
 #include <llvm/Target/TargetData.h>
 #include <llvm/Value.h>
 
@@ -33,15 +34,15 @@ using namespace CodeGen;
 namespace {
 class ItaniumCXXABI : public CodeGen::CGCXXABI {
 private:
-  const llvm::IntegerType *PtrDiffTy;
+  llvm::IntegerType *PtrDiffTy;
 protected:
   bool IsARM;
 
   // It's a little silly for us to cache this.
-  const llvm::IntegerType *getPtrDiffTy() {
+  llvm::IntegerType *getPtrDiffTy() {
     if (!PtrDiffTy) {
       QualType T = getContext().getPointerDiffType();
-      const llvm::Type *Ty = CGM.getTypes().ConvertTypeRecursive(T);
+      llvm::Type *Ty = CGM.getTypes().ConvertType(T);
       PtrDiffTy = cast<llvm::IntegerType>(Ty);
     }
     return PtrDiffTy;
@@ -57,7 +58,7 @@ public:
 
   bool isZeroInitializable(const MemberPointerType *MPT);
 
-  const llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT);
+  llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT);
 
   llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
                                                llvm::Value *&This,
@@ -175,13 +176,11 @@ CodeGen::CGCXXABI *CodeGen::CreateARMCXXABI(CodeGenModule &CGM) {
   return new ARMCXXABI(CGM);
 }
 
-const llvm::Type *
+llvm::Type *
 ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
   if (MPT->isMemberDataPointer())
     return getPtrDiffTy();
-  else
-    return llvm::StructType::get(CGM.getLLVMContext(),
-                                 getPtrDiffTy(), getPtrDiffTy(), NULL);
+  return llvm::StructType::get(getPtrDiffTy(), getPtrDiffTy(), NULL);
 }
 
 /// In the Itanium and ARM ABIs, method pointers have the form:
@@ -473,8 +472,7 @@ ItaniumCXXABI::EmitMemberPointerConversion(llvm::Constant *C,
   else
     Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset);
 
-  return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2,
-                                   /*Packed=*/false);
+  return llvm::ConstantStruct::get(CS->getType(), Values);
 }        
 
 
@@ -489,8 +487,7 @@ ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
 
   llvm::Constant *Zero = llvm::ConstantInt::get(ptrdiff_t, 0);
   llvm::Constant *Values[2] = { Zero, Zero };
-  return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2,
-                                   /*Packed=*/false);
+  return llvm::ConstantStruct::getAnon(Values);
 }
 
 llvm::Constant *
@@ -540,7 +537,7 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
     const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
     const llvm::Type *Ty;
     // Check whether the function has a computable LLVM signature.
-    if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
+    if (Types.isFuncTypeConvertible(FPT)) {
       // The function has a computable LLVM signature; use the correct type.
       Ty = Types.GetFunctionType(Types.getFunctionInfo(MD),
                                  FPT->isVariadic());
@@ -555,8 +552,7 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
     MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
   }
   
-  return llvm::ConstantStruct::get(CGM.getLLVMContext(),
-                                   MemPtr, 2, /*Packed=*/false);
+  return llvm::ConstantStruct::getAnon(MemPtr);
 }
 
 /// The comparison algorithm is pretty easy: the member pointers are
@@ -802,10 +798,27 @@ bool ItaniumCXXABI::NeedsArrayCookie(const CXXNewExpr *expr) {
   if (expr->doesUsualArrayDeleteWantSize())
     return true;
 
+  // Automatic Reference Counting:
+  //   We need an array cookie for pointers with strong or weak lifetime.
+  QualType AllocatedType = expr->getAllocatedType();
+  if (getContext().getLangOptions().ObjCAutoRefCount &&
+      AllocatedType->isObjCLifetimeType()) {
+    switch (AllocatedType.getObjCLifetime()) {
+    case Qualifiers::OCL_None:
+    case Qualifiers::OCL_ExplicitNone:
+    case Qualifiers::OCL_Autoreleasing:
+      return false;
+      
+    case Qualifiers::OCL_Strong:
+    case Qualifiers::OCL_Weak:
+      return true;
+    }
+  }
+
   // Otherwise, if the class has a non-trivial destructor, it always
   // needs a cookie.
   const CXXRecordDecl *record =
-    expr->getAllocatedType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
+    AllocatedType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
   return (record && !record->hasTrivialDestructor());
 }
 
@@ -816,6 +829,22 @@ bool ItaniumCXXABI::NeedsArrayCookie(const CXXDeleteExpr *expr,
   if (expr->doesUsualArrayDeleteWantSize())
     return true;
 
+  // Automatic Reference Counting:
+  //   We need an array cookie for pointers with strong or weak lifetime.
+  if (getContext().getLangOptions().ObjCAutoRefCount &&
+      elementType->isObjCLifetimeType()) {
+    switch (elementType.getObjCLifetime()) {
+    case Qualifiers::OCL_None:
+    case Qualifiers::OCL_ExplicitNone:
+    case Qualifiers::OCL_Autoreleasing:
+      return false;
+
+    case Qualifiers::OCL_Strong:
+    case Qualifiers::OCL_Weak:
+      return true;
+    }
+  }
+  
   // Otherwise, if the class has a non-trivial destructor, it always
   // needs a cookie.
   const CXXRecordDecl *record =
@@ -1005,31 +1034,34 @@ void ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF,
 /*********************** Static local initialization **************************/
 
 static llvm::Constant *getGuardAcquireFn(CodeGenModule &CGM,
-                                         const llvm::PointerType *GuardPtrTy) {
+                                         llvm::PointerType *GuardPtrTy) {
   // int __cxa_guard_acquire(__guard *guard_object);
+  llvm::Type *ArgTys[] = { GuardPtrTy };
   const llvm::FunctionType *FTy =
     llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy),
-                            GuardPtrTy, /*isVarArg=*/false);
+                            ArgTys, /*isVarArg=*/false);
   
   return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire");
 }
 
 static llvm::Constant *getGuardReleaseFn(CodeGenModule &CGM,
-                                         const llvm::PointerType *GuardPtrTy) {
+                                         llvm::PointerType *GuardPtrTy) {
   // void __cxa_guard_release(__guard *guard_object);
+  llvm::Type *ArgTys[] = { GuardPtrTy };
   const llvm::FunctionType *FTy =
     llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
-                            GuardPtrTy, /*isVarArg=*/false);
+                            ArgTys, /*isVarArg=*/false);
   
   return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release");
 }
 
 static llvm::Constant *getGuardAbortFn(CodeGenModule &CGM,
-                                       const llvm::PointerType *GuardPtrTy) {
+                                       llvm::PointerType *GuardPtrTy) {
   // void __cxa_guard_abort(__guard *guard_object);
+  llvm::Type *ArgTys[] = { GuardPtrTy };
   const llvm::FunctionType *FTy =
     llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
-                            GuardPtrTy, /*isVarArg=*/false);
+                            ArgTys, /*isVarArg=*/false);
   
   return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort");
 }
@@ -1039,7 +1071,7 @@ namespace {
     llvm::GlobalVariable *Guard;
     CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
 
-    void Emit(CodeGenFunction &CGF, bool IsForEH) {
+    void Emit(CodeGenFunction &CGF, Flags flags) {
       CGF.Builder.CreateCall(getGuardAbortFn(CGF.CGM, Guard->getType()), Guard)
         ->setDoesNotThrow();
     }
@@ -1055,21 +1087,21 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
 
   // We only need to use thread-safe statics for local variables;
   // global initialization is always single-threaded.
-  bool ThreadsafeStatics = (getContext().getLangOptions().ThreadsafeStatics &&
-                            D.isLocalVarDecl());
+  bool threadsafe =
+    (getContext().getLangOptions().ThreadsafeStatics && D.isLocalVarDecl());
 
   const llvm::IntegerType *GuardTy;
 
   // If we have a global variable with internal linkage and thread-safe statics
   // are disabled, we can just let the guard variable be of type i8.
-  bool UseInt8GuardVariable = !ThreadsafeStatics && GV->hasInternalLinkage();
-  if (UseInt8GuardVariable)
-    GuardTy = Builder.getInt8Ty();
-  else {
+  bool useInt8GuardVariable = !threadsafe && GV->hasInternalLinkage();
+  if (useInt8GuardVariable) {
+    GuardTy = CGF.Int8Ty;
+  } else {
     // Guard variables are 64 bits in the generic ABI and 32 bits on ARM.
-    GuardTy = (IsARM ? Builder.getInt32Ty() : Builder.getInt64Ty());
+    GuardTy = (IsARM ? CGF.Int32Ty : CGF.Int64Ty);
   }
-  const llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo();
+  llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo();
 
   // Create the guard variable.
   llvm::SmallString<256> GuardVName;
@@ -1099,7 +1131,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
   //       if (__cxa_guard_acquire(&obj_guard))
   //         ...
   //     }
-  if (IsARM && !UseInt8GuardVariable) {
+  if (IsARM && !useInt8GuardVariable) {
     llvm::Value *V = Builder.CreateLoad(GuardVariable);
     V = Builder.CreateAnd(V, Builder.getInt32(1));
     IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
@@ -1130,13 +1162,16 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
   llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
   llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
 
+  llvm::BasicBlock *NoCheckBlock = EndBlock;
+  if (threadsafe) NoCheckBlock = CGF.createBasicBlock("init.barrier");
+
   // Check if the first byte of the guard variable is zero.
-  Builder.CreateCondBr(IsInitialized, InitCheckBlock, EndBlock);
+  Builder.CreateCondBr(IsInitialized, InitCheckBlock, NoCheckBlock);
 
   CGF.EmitBlock(InitCheckBlock);
 
   // Variables used when coping with thread-safe statics and exceptions.
-  if (ThreadsafeStatics) {    
+  if (threadsafe) {    
     // Call __cxa_guard_acquire.
     llvm::Value *V
       = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable);
@@ -1155,7 +1190,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
   // Emit the initializer and add a global destructor if appropriate.
   CGF.EmitCXXGlobalVarDeclInit(D, GV);
 
-  if (ThreadsafeStatics) {
+  if (threadsafe) {
     // Pop the guard-abort cleanup if we pushed one.
     CGF.PopCleanupBlock();
 
@@ -1165,5 +1200,23 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
     Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable);
   }
 
+  // Emit an acquire memory barrier if using thread-safe statics:
+  // Itanium ABI:
+  //   An implementation supporting thread-safety on multiprocessor
+  //   systems must also guarantee that references to the initialized
+  //   object do not occur before the load of the initialization flag.
+  if (threadsafe) {
+    Builder.CreateBr(EndBlock);
+    CGF.EmitBlock(NoCheckBlock);
+
+    llvm::Value *_false = Builder.getFalse();
+    llvm::Value *_true = Builder.getTrue();
+
+    Builder.CreateCall5(CGM.getIntrinsic(llvm::Intrinsic::memory_barrier),
+                        /* load-load, load-store */ _true, _true,
+                        /* store-load, store-store */ _false, _false,
+                        /* device or I/O */ _false);
+  }
+
   CGF.EmitBlock(EndBlock);
 }
-- 
cgit v1.1