diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp | 123 | 
1 files changed, 88 insertions, 35 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp index 12ef9bd030bd..0c86080fa80e 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/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);  }  | 
