diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index debebf20ae6b..caf0668d6477 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -284,7 +284,7 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { // Now throw the exception. const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); - llvm::Constant *TypeInfo = CGM.GetAddrOfRTTI(ThrowType); + llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType); llvm::Constant *Dtor = llvm::Constant::getNullValue(Int8PtrTy); if (getInvokeDest()) { @@ -367,7 +367,7 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { for (unsigned i = 0; i < Proto->getNumExceptions(); ++i) { QualType Ty = Proto->getExceptionType(i); - llvm::Value *EHType = CGM.GetAddrOfRTTI(Ty.getNonReferenceType()); + llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(Ty.getNonReferenceType()); SelectorArgs.push_back(EHType); } if (Proto->getNumExceptions()) @@ -506,9 +506,9 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { const CXXCatchStmt *C = S.getHandler(i); VarDecl *CatchParam = C->getExceptionDecl(); if (CatchParam) { - llvm::Value *EHType - = CGM.GetAddrOfRTTI(C->getCaughtType().getNonReferenceType()); - SelectorArgs.push_back(EHType); + llvm::Value *EHTypeInfo + = CGM.GetAddrOfRTTIDescriptor(C->getCaughtType().getNonReferenceType()); + SelectorArgs.push_back(EHTypeInfo); } else { // null indicates catch all SelectorArgs.push_back(Null); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 7f827ccd8edc..6a3b8bf3c038 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -426,9 +426,12 @@ llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { QualType Ty = E->getType(); const llvm::Type *LTy = ConvertType(Ty)->getPointerTo(); - if (E->isTypeOperand()) - return Builder.CreateBitCast(CGM.GetAddrOfRTTI(E->getTypeOperand()), LTy); - + if (E->isTypeOperand()) { + llvm::Constant *TypeInfo = + CGM.GetAddrOfRTTIDescriptor(E->getTypeOperand()); + return Builder.CreateBitCast(TypeInfo, LTy); + } + Expr *subE = E->getExprOperand(); Ty = subE->getType(); CanQualType CanTy = CGM.getContext().getCanonicalType(Ty); @@ -468,24 +471,23 @@ llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL); V = Builder.CreateLoad(V); return V; - } - return Builder.CreateBitCast(CGM.GetAddrOfRTTI(RD), LTy); + } } - return Builder.CreateBitCast(CGM.GetAddrOfRTTI(Ty), LTy); + return Builder.CreateBitCast(CGM.GetAddrOfRTTIDescriptor(Ty), LTy); } llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE) { - QualType CastTy = DCE->getTypeAsWritten(); - QualType InnerType = CastTy->getPointeeType(); - QualType ArgTy = DCE->getSubExpr()->getType(); - const llvm::Type *LArgTy = ConvertType(ArgTy); + QualType SrcTy = DCE->getSubExpr()->getType(); + QualType DestTy = DCE->getTypeAsWritten(); + QualType InnerType = DestTy->getPointeeType(); + const llvm::Type *LTy = ConvertType(DCE->getType()); bool CanBeZero = false; bool ToVoid = false; bool ThrowOnBad = false; - if (CastTy->isPointerType()) { + if (DestTy->isPointerType()) { // FIXME: if PointerType->hasAttr(), we don't set this CanBeZero = true; if (InnerType->isVoidType()) @@ -495,14 +497,13 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V, ThrowOnBad = true; } - CXXRecordDecl *SrcTy; - QualType Ty = ArgTy; - if (ArgTy.getTypePtr()->isPointerType() - || ArgTy.getTypePtr()->isReferenceType()) - Ty = Ty.getTypePtr()->getPointeeType(); - CanQualType CanTy = CGM.getContext().getCanonicalType(Ty); - Ty = CanTy.getUnqualifiedType(); - SrcTy = cast(Ty->getAs()->getDecl()); + if (SrcTy->isPointerType() || SrcTy->isReferenceType()) + SrcTy = SrcTy->getPointeeType(); + SrcTy = SrcTy.getUnqualifiedType(); + + if (DestTy->isPointerType()) + DestTy = DestTy->getPointeeType(); + DestTy = DestTy.getUnqualifiedType(); llvm::BasicBlock *ContBlock = createBasicBlock(); llvm::BasicBlock *NullBlock = 0; @@ -510,15 +511,13 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V, if (CanBeZero) { NonZeroBlock = createBasicBlock(); NullBlock = createBasicBlock(); - llvm::Value *Zero = llvm::Constant::getNullValue(LArgTy); - Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), - NonZeroBlock, NullBlock); + Builder.CreateCondBr(Builder.CreateIsNotNull(V), NonZeroBlock, NullBlock); EmitBlock(NonZeroBlock); } llvm::BasicBlock *BadCastBlock = 0; - const llvm::Type *PtrDiffTy = ConvertType(getContext().getSizeType()); + const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType()); // See if this is a dynamic_cast(void*) if (ToVoid) { @@ -542,27 +541,25 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V, ArgTys.push_back(PtrToInt8Ty); ArgTys.push_back(PtrDiffTy); FTy = llvm::FunctionType::get(ResultType, ArgTys, false); - CXXRecordDecl *DstTy; - Ty = CastTy.getTypePtr()->getPointeeType(); - CanTy = CGM.getContext().getCanonicalType(Ty); - Ty = CanTy.getUnqualifiedType(); - DstTy = cast(Ty->getAs()->getDecl()); // FIXME: Calculate better hint. llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL); - llvm::Value *SrcArg = CGM.GetAddrOfRTTI(SrcTy); - llvm::Value *DstArg = CGM.GetAddrOfRTTI(DstTy); + + assert(SrcTy->isRecordType() && "Src type must be record type!"); + assert(DestTy->isRecordType() && "Dest type must be record type!"); + + llvm::Value *SrcArg = CGM.GetAddrOfRTTIDescriptor(SrcTy); + llvm::Value *DestArg = CGM.GetAddrOfRTTIDescriptor(DestTy); + V = Builder.CreateBitCast(V, PtrToInt8Ty); V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"), - V, SrcArg, DstArg, hint); + V, SrcArg, DestArg, hint); V = Builder.CreateBitCast(V, LTy); if (ThrowOnBad) { BadCastBlock = createBasicBlock(); - llvm::Value *Zero = llvm::Constant::getNullValue(LTy); - Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), - ContBlock, BadCastBlock); + Builder.CreateCondBr(Builder.CreateIsNotNull(V), ContBlock, BadCastBlock); EmitBlock(BadCastBlock); /// Call __cxa_bad_cast ResultType = llvm::Type::getVoidTy(VMContext); diff --git a/clang/lib/CodeGen/CGRTTI.cpp b/clang/lib/CodeGen/CGRTTI.cpp index 6471eaa824fe..b9255b58cd1f 100644 --- a/clang/lib/CodeGen/CGRTTI.cpp +++ b/clang/lib/CodeGen/CGRTTI.cpp @@ -46,6 +46,10 @@ class RTTIBuilder { TI_ContainingClassIncomplete = 0x10 }; + /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI + /// descriptor of the given type. + llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty); + public: RTTIBuilder(CodeGenModule &cgm) : CGM(cgm), VMContext(cgm.getModule().getContext()), @@ -124,29 +128,6 @@ public: return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), c); } - llvm::Constant *BuildTypeRef(QualType Ty) { - llvm::Constant *C; - - llvm::SmallString<256> OutName; - CGM.getMangleContext().mangleCXXRTTI(Ty, OutName); - llvm::StringRef Name = OutName.str(); - - C = CGM.getModule().getGlobalVariable(Name); - if (C) - return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); - - llvm::GlobalVariable::LinkageTypes linktype; - linktype = llvm::GlobalValue::ExternalLinkage;; - - C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype, - 0, Name); - return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); - } - - llvm::Constant *Buildclass_type_infoRef(const CXXRecordDecl *RD) { - return BuildTypeRef(CGM.getContext().getTagDeclType(RD)); - } - /// CalculateFlags - Calculate the flags for the __vmi_class_type_info /// datastructure. 1 for non-diamond repeated inheritance, 2 for a dimond /// shaped class. @@ -256,9 +237,10 @@ public: const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { + QualType BaseType = i->getType(); const CXXRecordDecl *Base = - cast(i->getType()->getAs()->getDecl()); - Info.push_back(CGM.GetAddrOfRTTI(Base)); + cast(BaseType->getAs()->getDecl()); + Info.push_back(CGM.GetAddrOfRTTIDescriptor(BaseType)); if (simple) break; int64_t offset; @@ -412,7 +394,7 @@ public: case Type::Builtin: { // We expect all type_info objects for builtin types to be in the library. - return BuildTypeRef(Ty); + return GetAddrOfExternalRTTIDescriptor(Ty); } case Type::Pointer: { @@ -421,7 +403,7 @@ public: Q.removeConst(); // T* and const T* for all builtin types T are expected in the library. if (isa(PTy) && Q.empty()) - return BuildTypeRef(Ty); + return GetAddrOfExternalRTTIDescriptor(Ty); return BuildPointerType(Ty); } @@ -456,7 +438,8 @@ public: return Buildclass_type_info(RD, llvm::GlobalValue::ExternalLinkage); // Otherwise, we just want a reference to the type info. - return Buildclass_type_infoRef(RD); + QualType Ty = CGM.getContext().getTagDeclType(RD); + return GetAddrOfExternalRTTIDescriptor(Ty); } // If there is no key function (or if the record doesn't have any virtual @@ -467,16 +450,25 @@ public: }; } -llvm::Constant *CodeGenModule::GetAddrOfRTTI(const CXXRecordDecl *RD) { - if (!getContext().getLangOptions().RTTI) { - const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); - return llvm::Constant::getNullValue(Int8PtrTy); +llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) { + // Mangle the RTTI name. + llvm::SmallString<256> OutName; + CGM.getMangleContext().mangleCXXRTTI(Ty, OutName); + llvm::StringRef Name = OutName.str(); + + // Look for an existing global variable. + llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); + + if (!GV) { + // Create a new global variable. + GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, /*Constant=*/true, + llvm::GlobalValue::ExternalLinkage, 0, Name); } - return RTTIBuilder(*this).BuildClassTypeInfo(RD); + return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); } -llvm::Constant *CodeGenModule::GetAddrOfRTTI(QualType Ty) { +llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty) { if (!getContext().getLangOptions().RTTI) { const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); return llvm::Constant::getNullValue(Int8PtrTy); diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp index 5283ed9366c3..d25f80d888e6 100644 --- a/clang/lib/CodeGen/CGVtable.cpp +++ b/clang/lib/CodeGen/CGVtable.cpp @@ -202,8 +202,10 @@ public: Extern(!l->isInAnonymousNamespace()), LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) { Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); - if (BuildVtable) - rtti = CGM.GetAddrOfRTTI(MostDerivedClass); + if (BuildVtable) { + QualType ClassType = CGM.getContext().getTagDeclType(MostDerivedClass); + rtti = CGM.GetAddrOfRTTIDescriptor(ClassType); + } } // getVtableComponents - Returns a reference to the vtable components. diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 20c71dc89b8a..814b1ef69465 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -212,12 +212,9 @@ public: llvm::Constant *GetAddrOfFunction(GlobalDecl GD, const llvm::Type *Ty = 0); - /// GetAddrOfRTTI - Get the address of the RTTI structure for the given type. - llvm::Constant *GetAddrOfRTTI(QualType Ty); - - /// GetAddrOfRTTI - Get the address of the RTTI structure for the given record - /// decl. - llvm::Constant *GetAddrOfRTTI(const CXXRecordDecl *RD); + /// GetAddrOfRTTIDescriptor - Get the address of the RTTI descriptor + /// for the given type. + llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty); llvm::Constant *GetAddrOfThunk(GlobalDecl GD, const ThunkAdjustment &ThisAdjustment);