diff options
Diffstat (limited to 'lib/CodeGen')
30 files changed, 2222 insertions, 1434 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 9e44db0..1bece7f 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -460,7 +460,8 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() { return GenericExtendedBlockLiteralType; } -RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) { +RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E, + ReturnValueSlot ReturnValue) { const BlockPointerType *BPT = E->getCallee()->getType()->getAs<BlockPointerType>(); @@ -509,7 +510,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) { Func = Builder.CreateBitCast(Func, BlockFTyPtr); // And call the block. - return EmitCall(FnInfo, Func, Args); + return EmitCall(FnInfo, Func, ReturnValue, Args); } uint64_t CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) { diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index c704432..866c587 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -209,10 +209,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, const llvm::Type *ResType[] = { ConvertType(E->getType()) }; + + // LLVM only supports 0 and 2, make sure that we pass along that + // as a boolean. + Value *Ty = EmitScalarExpr(E->getArg(1)); + ConstantInt *CI = dyn_cast<ConstantInt>(Ty); + assert(CI); + uint64_t val = CI->getZExtValue(); + CI = ConstantInt::get(llvm::Type::getInt1Ty(VMContext), (val & 0x2) >> 1); + Value *F = CGM.getIntrinsic(Intrinsic::objectsize, ResType, 1); return RValue::get(Builder.CreateCall2(F, EmitScalarExpr(E->getArg(0)), - EmitScalarExpr(E->getArg(1)))); + CI)); } case Builtin::BI__builtin_prefetch: { Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0)); @@ -229,6 +238,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Builder.CreateCall(F)); } case Builtin::BI__builtin_unreachable: { + if (CatchUndefined && HaveInsertPoint()) + EmitBranch(getTrapBB()); Value *V = Builder.CreateUnreachable(); Builder.ClearInsertionPoint(); return RValue::get(V); @@ -300,6 +311,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); return RValue::get(Address); } + case Builtin::BImemcpy: case Builtin::BI__builtin_memcpy: { Value *Address = EmitScalarExpr(E->getArg(0)); Builder.CreateCall4(CGM.getMemCpyFn(), Address, @@ -308,6 +320,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); return RValue::get(Address); } + case Builtin::BImemmove: case Builtin::BI__builtin_memmove: { Value *Address = EmitScalarExpr(E->getArg(0)); Builder.CreateCall4(CGM.getMemMoveFn(), Address, @@ -316,6 +329,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); return RValue::get(Address); } + case Builtin::BImemset: case Builtin::BI__builtin_memset: { Value *Address = EmitScalarExpr(E->getArg(0)); Builder.CreateCall4(CGM.getMemSetFn(), Address, @@ -326,12 +340,20 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Address); } case Builtin::BI__builtin_return_address: { + Value *Depth = EmitScalarExpr(E->getArg(0)); + Depth = Builder.CreateIntCast(Depth, + llvm::Type::getInt32Ty(VMContext), + false, "tmp"); Value *F = CGM.getIntrinsic(Intrinsic::returnaddress, 0, 0); - return RValue::get(Builder.CreateCall(F, EmitScalarExpr(E->getArg(0)))); + return RValue::get(Builder.CreateCall(F, Depth)); } case Builtin::BI__builtin_frame_address: { + Value *Depth = EmitScalarExpr(E->getArg(0)); + Depth = Builder.CreateIntCast(Depth, + llvm::Type::getInt32Ty(VMContext), + false, "tmp"); Value *F = CGM.getIntrinsic(Intrinsic::frameaddress, 0, 0); - return RValue::get(Builder.CreateCall(F, EmitScalarExpr(E->getArg(0)))); + return RValue::get(Builder.CreateCall(F, Depth)); } case Builtin::BI__builtin_extract_return_addr: { // FIXME: There should be a target hook for this @@ -565,9 +587,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, // that function. if (getContext().BuiltinInfo.isLibFunction(BuiltinID) || getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return EmitCall(CGM.getBuiltinLibFunction(FD, BuiltinID), - E->getCallee()->getType(), E->arg_begin(), - E->arg_end()); + return EmitCall(E->getCallee()->getType(), + CGM.getBuiltinLibFunction(FD, BuiltinID), + ReturnValueSlot(), + E->arg_begin(), E->arg_end()); // See if we have a target specific intrinsic. const char *Name = getContext().BuiltinInfo.GetName(BuiltinID); @@ -848,7 +871,5 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { - switch (BuiltinID) { - default: return 0; - } + return 0; } diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 0d11be2..cc006d9 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -28,6 +28,7 @@ using namespace CodeGen; RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, llvm::Value *Callee, + ReturnValueSlot ReturnValue, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd) { @@ -46,8 +47,8 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType(); - return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), - Callee, Args, MD); + return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, + ReturnValue, Args, MD); } /// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given @@ -78,9 +79,10 @@ static bool canDevirtualizeMemberFunctionCalls(const Expr *Base) { return false; } -RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { +RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, + ReturnValueSlot ReturnValue) { if (isa<BinaryOperator>(CE->getCallee()->IgnoreParens())) - return EmitCXXMemberPointerCallExpr(CE); + return EmitCXXMemberPointerCallExpr(CE, ReturnValue); const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()->IgnoreParens()); const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl()); @@ -88,9 +90,8 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { if (MD->isStatic()) { // The method is static, emit it as we would a regular call. llvm::Value *Callee = CGM.GetAddrOfFunction(MD); - return EmitCall(Callee, getContext().getPointerType(MD->getType()), - CE->arg_begin(), CE->arg_end(), 0); - + return EmitCall(getContext().getPointerType(MD->getType()), Callee, + ReturnValue, CE->arg_begin(), CE->arg_end()); } const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); @@ -139,12 +140,13 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { Callee = CGM.GetAddrOfFunction(MD, Ty); } - return EmitCXXMemberCall(MD, Callee, This, + return EmitCXXMemberCall(MD, Callee, ReturnValue, This, CE->arg_begin(), CE->arg_end()); } RValue -CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E) { +CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, + ReturnValueSlot ReturnValue) { const BinaryOperator *BO = cast<BinaryOperator>(E->getCallee()->IgnoreParens()); const Expr *BaseExpr = BO->getLHS(); @@ -247,13 +249,14 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E) { // And the rest of the call args EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end()); QualType ResultType = BO->getType()->getAs<FunctionType>()->getResultType(); - return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), - Callee, Args, 0); + return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, + ReturnValue, Args); } RValue CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, - const CXXMethodDecl *MD) { + const CXXMethodDecl *MD, + ReturnValueSlot ReturnValue) { assert(MD->isInstance() && "Trying to emit a member call expr on a static method!"); @@ -283,7 +286,7 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, else Callee = CGM.GetAddrOfFunction(MD, Ty); - return EmitCXXMemberCall(MD, Callee, This, + return EmitCXXMemberCall(MD, Callee, ReturnValue, This, E->arg_begin() + 1, E->arg_end()); } @@ -508,7 +511,7 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd) { - if (D->isCopyConstructor(getContext())) { + if (D->isCopyConstructor()) { const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D->getDeclContext()); if (ClassDecl->hasTrivialCopyConstructor()) { assert(!ClassDecl->hasUserDeclaredCopyConstructor() && @@ -527,7 +530,7 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); - EmitCXXMemberCall(D, Callee, This, ArgBeg, ArgEnd); + EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, ArgBeg, ArgEnd); } void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, @@ -552,7 +555,8 @@ void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, // FIXME: We should try to share this code with EmitCXXMemberCall. QualType ResultType = DD->getType()->getAs<FunctionType>()->getResultType(); - EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, Args, DD); + EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, + ReturnValueSlot(), Args, DD); } void @@ -564,22 +568,33 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, getContext().getAsConstantArrayType(E->getType()); // For a copy constructor, even if it is trivial, must fall thru so // its argument is code-gen'ed. - if (!CD->isCopyConstructor(getContext())) { + if (!CD->isCopyConstructor()) { QualType InitType = E->getType(); if (Array) InitType = getContext().getBaseElementType(Array); const CXXRecordDecl *RD = cast<CXXRecordDecl>(InitType->getAs<RecordType>()->getDecl()); if (RD->hasTrivialConstructor()) - return; + return; } // Code gen optimization to eliminate copy constructor and return // its first argument instead. if (getContext().getLangOptions().ElideConstructors && E->isElidable()) { const Expr *Arg = E->getArg(0); - + + if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) { + assert((ICE->getCastKind() == CastExpr::CK_NoOp || + ICE->getCastKind() == CastExpr::CK_ConstructorConversion || + ICE->getCastKind() == CastExpr::CK_UserDefinedConversion) && + "Unknown implicit cast kind in constructor elision"); + Arg = ICE->getSubExpr(); + } + + if (const CXXFunctionalCastExpr *FCE = dyn_cast<CXXFunctionalCastExpr>(Arg)) + Arg = FCE->getSubExpr(); + if (const CXXBindTemporaryExpr *BindExpr = - dyn_cast<CXXBindTemporaryExpr>(Arg)) + dyn_cast<CXXBindTemporaryExpr>(Arg)) Arg = BindExpr->getSubExpr(); EmitAggExpr(Arg, Dest, false); @@ -591,6 +606,7 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, BasePtr = llvm::PointerType::getUnqual(BasePtr); llvm::Value *BaseAddrPtr = Builder.CreateBitCast(Dest, BasePtr); + EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr, E->arg_begin(), E->arg_end()); } @@ -793,7 +809,7 @@ CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, } RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), - Callee, CallArgs, MD); + Callee, ReturnValueSlot(), CallArgs, MD); if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) { bool CanBeZero = !(ResultType->isReferenceType() // FIXME: attr nonnull can't be zero either @@ -1043,765 +1059,70 @@ CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type, return ::BuildVirtualCall(*this, VtableIndex, This, Ty); } -/// EmitClassAggrMemberwiseCopy - This routine generates code to copy a class -/// array of objects from SrcValue to DestValue. Copying can be either a bitwise -/// copy or via a copy constructor call. -// FIXME. Consolidate this with EmitCXXAggrConstructorCall. -void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest, - llvm::Value *Src, - const ArrayType *Array, - const CXXRecordDecl *BaseClassDecl, - QualType Ty) { - const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); - assert(CA && "VLA cannot be copied over"); - bool BitwiseCopy = BaseClassDecl->hasTrivialCopyConstructor(); - - // Create a temporary for the loop index and initialize it with 0. - llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), - "loop.index"); - llvm::Value* zeroConstant = - llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); - Builder.CreateStore(zeroConstant, IndexPtr); - // Start the loop with a block that tests the condition. - llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); - llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); - - EmitBlock(CondBlock); - - llvm::BasicBlock *ForBody = createBasicBlock("for.body"); - // Generate: if (loop-index < number-of-elements fall to the loop body, - // otherwise, go to the block after the for-loop. - uint64_t NumElements = getContext().getConstantArrayElementCount(CA); - llvm::Value * NumElementsPtr = - llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); - llvm::Value *Counter = Builder.CreateLoad(IndexPtr); - llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, - "isless"); - // If the condition is true, execute the body. - Builder.CreateCondBr(IsLess, ForBody, AfterFor); - - EmitBlock(ForBody); - llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); - // Inside the loop body, emit the constructor call on the array element. - Counter = Builder.CreateLoad(IndexPtr); - Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); - Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); - if (BitwiseCopy) - EmitAggregateCopy(Dest, Src, Ty); - else if (CXXConstructorDecl *BaseCopyCtor = - BaseClassDecl->getCopyConstructor(getContext(), 0)) { - llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, - Ctor_Complete); - CallArgList CallArgs; - // Push the this (Dest) ptr. - CallArgs.push_back(std::make_pair(RValue::get(Dest), - BaseCopyCtor->getThisType(getContext()))); - - // Push the Src ptr. - CallArgs.push_back(std::make_pair(RValue::get(Src), - BaseCopyCtor->getParamDecl(0)->getType())); - QualType ResultType = - BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType(); - EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), - Callee, CallArgs, BaseCopyCtor); - } - EmitBlock(ContinueBlock); - - // Emit the increment of the loop counter. - llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); - Counter = Builder.CreateLoad(IndexPtr); - NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); - Builder.CreateStore(NextVal, IndexPtr); - - // Finally, branch back up to the condition for the next iteration. - EmitBranch(CondBlock); - - // Emit the fall-through block. - EmitBlock(AfterFor, true); -} - -/// EmitClassAggrCopyAssignment - This routine generates code to assign a class -/// array of objects from SrcValue to DestValue. Assignment can be either a -/// bitwise assignment or via a copy assignment operator function call. -/// FIXME. This can be consolidated with EmitClassAggrMemberwiseCopy -void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest, - llvm::Value *Src, - const ArrayType *Array, - const CXXRecordDecl *BaseClassDecl, - QualType Ty) { - const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); - assert(CA && "VLA cannot be asssigned"); - bool BitwiseAssign = BaseClassDecl->hasTrivialCopyAssignment(); - - // Create a temporary for the loop index and initialize it with 0. - llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), - "loop.index"); - llvm::Value* zeroConstant = - llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); - Builder.CreateStore(zeroConstant, IndexPtr); - // Start the loop with a block that tests the condition. - llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); - llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); - - EmitBlock(CondBlock); - - llvm::BasicBlock *ForBody = createBasicBlock("for.body"); - // Generate: if (loop-index < number-of-elements fall to the loop body, - // otherwise, go to the block after the for-loop. - uint64_t NumElements = getContext().getConstantArrayElementCount(CA); - llvm::Value * NumElementsPtr = - llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); - llvm::Value *Counter = Builder.CreateLoad(IndexPtr); - llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, - "isless"); - // If the condition is true, execute the body. - Builder.CreateCondBr(IsLess, ForBody, AfterFor); - - EmitBlock(ForBody); - llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); - // Inside the loop body, emit the assignment operator call on array element. - Counter = Builder.CreateLoad(IndexPtr); - Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); - Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); - const CXXMethodDecl *MD = 0; - if (BitwiseAssign) - EmitAggregateCopy(Dest, Src, Ty); - else { - bool hasCopyAssign = BaseClassDecl->hasConstCopyAssignment(getContext(), - MD); - assert(hasCopyAssign && "EmitClassAggrCopyAssignment - No user assign"); - (void)hasCopyAssign; - const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); - const llvm::Type *LTy = - CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), - FPT->isVariadic()); - llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy); - - CallArgList CallArgs; - // Push the this (Dest) ptr. - CallArgs.push_back(std::make_pair(RValue::get(Dest), - MD->getThisType(getContext()))); - - // Push the Src ptr. - CallArgs.push_back(std::make_pair(RValue::get(Src), - MD->getParamDecl(0)->getType())); - QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType(); - EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), - Callee, CallArgs, MD); - } - EmitBlock(ContinueBlock); - - // Emit the increment of the loop counter. - llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); - Counter = Builder.CreateLoad(IndexPtr); - NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); - Builder.CreateStore(NextVal, IndexPtr); - - // Finally, branch back up to the condition for the next iteration. - EmitBranch(CondBlock); - - // Emit the fall-through block. - EmitBlock(AfterFor, true); -} - -/// EmitClassMemberwiseCopy - This routine generates code to copy a class -/// object from SrcValue to DestValue. Copying can be either a bitwise copy -/// or via a copy constructor call. -void CodeGenFunction::EmitClassMemberwiseCopy( - llvm::Value *Dest, llvm::Value *Src, - const CXXRecordDecl *ClassDecl, - const CXXRecordDecl *BaseClassDecl, QualType Ty) { - if (ClassDecl) { - Dest = GetAddressOfBaseClass(Dest, ClassDecl, BaseClassDecl, - /*NullCheckValue=*/false); - Src = GetAddressOfBaseClass(Src, ClassDecl, BaseClassDecl, - /*NullCheckValue=*/false); - } - if (BaseClassDecl->hasTrivialCopyConstructor()) { - EmitAggregateCopy(Dest, Src, Ty); - return; - } - - if (CXXConstructorDecl *BaseCopyCtor = - BaseClassDecl->getCopyConstructor(getContext(), 0)) { - llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, - Ctor_Complete); - CallArgList CallArgs; - // Push the this (Dest) ptr. - CallArgs.push_back(std::make_pair(RValue::get(Dest), - BaseCopyCtor->getThisType(getContext()))); - - // Push the Src ptr. - CallArgs.push_back(std::make_pair(RValue::get(Src), - BaseCopyCtor->getParamDecl(0)->getType())); - QualType ResultType = - BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType(); - EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), - Callee, CallArgs, BaseCopyCtor); - } -} - -/// EmitClassCopyAssignment - This routine generates code to copy assign a class -/// object from SrcValue to DestValue. Assignment can be either a bitwise -/// assignment of via an assignment operator call. -// FIXME. Consolidate this with EmitClassMemberwiseCopy as they share a lot. -void CodeGenFunction::EmitClassCopyAssignment( - llvm::Value *Dest, llvm::Value *Src, - const CXXRecordDecl *ClassDecl, - const CXXRecordDecl *BaseClassDecl, - QualType Ty) { - if (ClassDecl) { - Dest = GetAddressOfBaseClass(Dest, ClassDecl, BaseClassDecl, - /*NullCheckValue=*/false); - Src = GetAddressOfBaseClass(Src, ClassDecl, BaseClassDecl, - /*NullCheckValue=*/false); - } - if (BaseClassDecl->hasTrivialCopyAssignment()) { - EmitAggregateCopy(Dest, Src, Ty); +void CodeGenFunction::InitializeVtablePtrs(const CXXRecordDecl *ClassDecl) { + if (!ClassDecl->isDynamicClass()) return; - } - - const CXXMethodDecl *MD = 0; - bool ConstCopyAssignOp = BaseClassDecl->hasConstCopyAssignment(getContext(), - MD); - assert(ConstCopyAssignOp && "EmitClassCopyAssignment - missing copy assign"); - (void)ConstCopyAssignOp; - - const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); - const llvm::Type *LTy = - CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), - FPT->isVariadic()); - llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy); - - CallArgList CallArgs; - // Push the this (Dest) ptr. - CallArgs.push_back(std::make_pair(RValue::get(Dest), - MD->getThisType(getContext()))); - - // Push the Src ptr. - CallArgs.push_back(std::make_pair(RValue::get(Src), - MD->getParamDecl(0)->getType())); - QualType ResultType = - MD->getType()->getAs<FunctionType>()->getResultType(); - EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), - Callee, CallArgs, MD); -} - -/// SynthesizeDefaultConstructor - synthesize a default constructor -void -CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor, - CXXCtorType Type, - llvm::Function *Fn, - const FunctionArgList &Args) { - assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor"); - StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args, - SourceLocation()); - EmitCtorPrologue(Ctor, Type); - FinishFunction(); -} - -/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a -/// copy constructor, in accordance with section 12.8 (p7 and p8) of C++03 -/// The implicitly-defined copy constructor for class X performs a memberwise -/// copy of its subobjects. The order of copying is the same as the order of -/// initialization of bases and members in a user-defined constructor -/// Each subobject is copied in the manner appropriate to its type: -/// if the subobject is of class type, the copy constructor for the class is -/// used; -/// if the subobject is an array, each element is copied, in the manner -/// appropriate to the element type; -/// if the subobject is of scalar type, the built-in assignment operator is -/// used. -/// Virtual base class subobjects shall be copied only once by the -/// implicitly-defined copy constructor - -void -CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, - CXXCtorType Type, - llvm::Function *Fn, - const FunctionArgList &Args) { - const CXXRecordDecl *ClassDecl = Ctor->getParent(); - assert(!ClassDecl->hasUserDeclaredCopyConstructor() && - "SynthesizeCXXCopyConstructor - copy constructor has definition already"); - assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor"); - StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args, - SourceLocation()); - - FunctionArgList::const_iterator i = Args.begin(); - const VarDecl *ThisArg = i->first; - llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg); - llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this"); - const VarDecl *SrcArg = (i+1)->first; - llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg); - llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj); - - for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); - Base != ClassDecl->bases_end(); ++Base) { - // FIXME. copy constrution of virtual base NYI - if (Base->isVirtual()) - continue; - - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - EmitClassMemberwiseCopy(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl, - Base->getType()); - } - for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), - E = ClassDecl->field_end(); I != E; ++I) { - const FieldDecl *Field = *I; - - QualType FieldType = getContext().getCanonicalType(Field->getType()); - const ConstantArrayType *Array = - getContext().getAsConstantArrayType(FieldType); - if (Array) - FieldType = getContext().getBaseElementType(FieldType); - - if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { - CXXRecordDecl *FieldClassDecl - = cast<CXXRecordDecl>(FieldClassType->getDecl()); - LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); - LValue RHS = EmitLValueForField(LoadOfSrc, Field, false, 0); - if (Array) { - const llvm::Type *BasePtr = ConvertType(FieldType); - BasePtr = llvm::PointerType::getUnqual(BasePtr); - llvm::Value *DestBaseAddrPtr = - Builder.CreateBitCast(LHS.getAddress(), BasePtr); - llvm::Value *SrcBaseAddrPtr = - Builder.CreateBitCast(RHS.getAddress(), BasePtr); - EmitClassAggrMemberwiseCopy(DestBaseAddrPtr, SrcBaseAddrPtr, Array, - FieldClassDecl, FieldType); - } - else - EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(), - 0 /*ClassDecl*/, FieldClassDecl, FieldType); - continue; - } - - if (Field->getType()->isReferenceType()) { - unsigned FieldIndex = CGM.getTypes().getLLVMFieldNo(Field); - - llvm::Value *LHS = Builder.CreateStructGEP(LoadOfThis, FieldIndex, - "lhs.ref"); - - llvm::Value *RHS = Builder.CreateStructGEP(LoadOfThis, FieldIndex, - "rhs.ref"); - - // Load the value in RHS. - RHS = Builder.CreateLoad(RHS); - - // And store it in the LHS - Builder.CreateStore(RHS, LHS); - - continue; - } - // Do a built-in assignment of scalar data members. - LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); - LValue RHS = EmitLValueForField(LoadOfSrc, Field, false, 0); - - if (!hasAggregateLLVMType(Field->getType())) { - RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType()); - EmitStoreThroughLValue(RVRHS, LHS, Field->getType()); - } else if (Field->getType()->isAnyComplexType()) { - ComplexPairTy Pair = LoadComplexFromAddr(RHS.getAddress(), - RHS.isVolatileQualified()); - StoreComplexToAddr(Pair, LHS.getAddress(), LHS.isVolatileQualified()); - } else { - EmitAggregateCopy(LHS.getAddress(), RHS.getAddress(), Field->getType()); - } - } - - InitializeVtablePtrs(ClassDecl); - FinishFunction(); -} - -/// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator. -/// Before the implicitly-declared copy assignment operator for a class is -/// implicitly defined, all implicitly- declared copy assignment operators for -/// its direct base classes and its nonstatic data members shall have been -/// implicitly defined. [12.8-p12] -/// The implicitly-defined copy assignment operator for class X performs -/// memberwise assignment of its subob- jects. The direct base classes of X are -/// assigned first, in the order of their declaration in -/// the base-specifier-list, and then the immediate nonstatic data members of X -/// are assigned, in the order in which they were declared in the class -/// definition.Each subobject is assigned in the manner appropriate to its type: -/// if the subobject is of class type, the copy assignment operator for the -/// class is used (as if by explicit qualification; that is, ignoring any -/// possible virtual overriding functions in more derived classes); -/// -/// if the subobject is an array, each element is assigned, in the manner -/// appropriate to the element type; -/// -/// if the subobject is of scalar type, the built-in assignment operator is -/// used. -void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD, - llvm::Function *Fn, - const FunctionArgList &Args) { - - const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); - assert(!ClassDecl->hasUserDeclaredCopyAssignment() && - "SynthesizeCXXCopyAssignment - copy assignment has user declaration"); - StartFunction(CD, CD->getResultType(), Fn, Args, SourceLocation()); - - FunctionArgList::const_iterator i = Args.begin(); - const VarDecl *ThisArg = i->first; - llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg); - llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this"); - const VarDecl *SrcArg = (i+1)->first; - llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg); - llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj); - - for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); - Base != ClassDecl->bases_end(); ++Base) { - // FIXME. copy assignment of virtual base NYI - if (Base->isVirtual()) - continue; + llvm::Constant *Vtable = CGM.getVtableInfo().getVtable(ClassDecl); + CodeGenModule::AddrSubMap_t& AddressPoints = + *(*CGM.AddressPoints[ClassDecl])[ClassDecl]; + llvm::Value *ThisPtr = LoadCXXThis(); + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl); + // Store address points for virtual bases + for (CXXRecordDecl::base_class_const_iterator I = + ClassDecl->vbases_begin(), E = ClassDecl->vbases_end(); I != E; ++I) { + const CXXBaseSpecifier &Base = *I; CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - EmitClassCopyAssignment(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl, - Base->getType()); - } - - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), - FieldEnd = ClassDecl->field_end(); - Field != FieldEnd; ++Field) { - QualType FieldType = getContext().getCanonicalType((*Field)->getType()); - const ConstantArrayType *Array = - getContext().getAsConstantArrayType(FieldType); - if (Array) - FieldType = getContext().getBaseElementType(FieldType); - - if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { - CXXRecordDecl *FieldClassDecl - = cast<CXXRecordDecl>(FieldClassType->getDecl()); - LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); - LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); - if (Array) { - const llvm::Type *BasePtr = ConvertType(FieldType); - BasePtr = llvm::PointerType::getUnqual(BasePtr); - llvm::Value *DestBaseAddrPtr = - Builder.CreateBitCast(LHS.getAddress(), BasePtr); - llvm::Value *SrcBaseAddrPtr = - Builder.CreateBitCast(RHS.getAddress(), BasePtr); - EmitClassAggrCopyAssignment(DestBaseAddrPtr, SrcBaseAddrPtr, Array, - FieldClassDecl, FieldType); - } - else - EmitClassCopyAssignment(LHS.getAddress(), RHS.getAddress(), - 0 /*ClassDecl*/, FieldClassDecl, FieldType); - continue; - } - // Do a built-in assignment of scalar data members. - LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); - LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); - if (!hasAggregateLLVMType(Field->getType())) { - RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType()); - EmitStoreThroughLValue(RVRHS, LHS, Field->getType()); - } else if (Field->getType()->isAnyComplexType()) { - ComplexPairTy Pair = LoadComplexFromAddr(RHS.getAddress(), - RHS.isVolatileQualified()); - StoreComplexToAddr(Pair, LHS.getAddress(), LHS.isVolatileQualified()); - } else { - EmitAggregateCopy(LHS.getAddress(), RHS.getAddress(), Field->getType()); - } - } - - // return *this; - Builder.CreateStore(LoadOfThis, ReturnValue); - - FinishFunction(); -} - -static void EmitBaseInitializer(CodeGenFunction &CGF, - const CXXRecordDecl *ClassDecl, - CXXBaseOrMemberInitializer *BaseInit, - CXXCtorType CtorType) { - assert(BaseInit->isBaseInitializer() && - "Must have base initializer!"); - - llvm::Value *ThisPtr = CGF.LoadCXXThis(); - - const Type *BaseType = BaseInit->getBaseClass(); - CXXRecordDecl *BaseClassDecl = - cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); - llvm::Value *V = CGF.GetAddressOfBaseClass(ThisPtr, ClassDecl, - BaseClassDecl, - /*NullCheckValue=*/false); - CGF.EmitCXXConstructorCall(BaseInit->getConstructor(), - CtorType, V, - BaseInit->const_arg_begin(), - BaseInit->const_arg_end()); -} - -static void EmitMemberInitializer(CodeGenFunction &CGF, - const CXXRecordDecl *ClassDecl, - CXXBaseOrMemberInitializer *MemberInit) { - assert(MemberInit->isMemberInitializer() && - "Must have member initializer!"); - - // non-static data member initializers. - FieldDecl *Field = MemberInit->getMember(); - QualType FieldType = CGF.getContext().getCanonicalType(Field->getType()); - - llvm::Value *ThisPtr = CGF.LoadCXXThis(); - LValue LHS; - if (FieldType->isReferenceType()) { - // FIXME: This is really ugly; should be refactored somehow - unsigned idx = CGF.CGM.getTypes().getLLVMFieldNo(Field); - llvm::Value *V = CGF.Builder.CreateStructGEP(ThisPtr, idx, "tmp"); - assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs"); - LHS = LValue::MakeAddr(V, CGF.MakeQualifiers(FieldType)); - } else { - LHS = CGF.EmitLValueForField(ThisPtr, Field, ClassDecl->isUnion(), 0); - } - - // If we are initializing an anonymous union field, drill down to the field. - if (MemberInit->getAnonUnionMember()) { - Field = MemberInit->getAnonUnionMember(); - LHS = CGF.EmitLValueForField(LHS.getAddress(), Field, - /*IsUnion=*/true, 0); - FieldType = Field->getType(); - } - - // If the field is an array, branch based on the element type. - const ConstantArrayType *Array = - CGF.getContext().getAsConstantArrayType(FieldType); - if (Array) - FieldType = CGF.getContext().getBaseElementType(FieldType); - - // We lose the constructor for anonymous union members, so handle them - // explicitly. - // FIXME: This is somwhat ugly. - if (MemberInit->getAnonUnionMember() && FieldType->getAs<RecordType>()) { - if (MemberInit->getNumArgs()) - CGF.EmitAggExpr(*MemberInit->arg_begin(), LHS.getAddress(), - LHS.isVolatileQualified()); - else - CGF.EmitAggregateClear(LHS.getAddress(), Field->getType()); - return; - } - - if (FieldType->getAs<RecordType>()) { - assert(MemberInit->getConstructor() && - "EmitCtorPrologue - no constructor to initialize member"); - if (Array) { - const llvm::Type *BasePtr = CGF.ConvertType(FieldType); - BasePtr = llvm::PointerType::getUnqual(BasePtr); - llvm::Value *BaseAddrPtr = - CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr); - CGF.EmitCXXAggrConstructorCall(MemberInit->getConstructor(), - Array, BaseAddrPtr, - MemberInit->const_arg_begin(), - MemberInit->const_arg_end()); - } - else - CGF.EmitCXXConstructorCall(MemberInit->getConstructor(), - Ctor_Complete, LHS.getAddress(), - MemberInit->const_arg_begin(), - MemberInit->const_arg_end()); - return; - } - - assert(MemberInit->getNumArgs() == 1 && "Initializer count must be 1 only"); - Expr *RhsExpr = *MemberInit->arg_begin(); - RValue RHS; - if (FieldType->isReferenceType()) { - RHS = CGF.EmitReferenceBindingToExpr(RhsExpr, FieldType, - /*IsInitializer=*/true); - CGF.EmitStoreThroughLValue(RHS, LHS, FieldType); - } else if (Array) { - CGF.EmitMemSetToZero(LHS.getAddress(), Field->getType()); - } else if (!CGF.hasAggregateLLVMType(RhsExpr->getType())) { - RHS = RValue::get(CGF.EmitScalarExpr(RhsExpr, true)); - CGF.EmitStoreThroughLValue(RHS, LHS, FieldType); - } else if (RhsExpr->getType()->isAnyComplexType()) { - CGF.EmitComplexExprIntoAddr(RhsExpr, LHS.getAddress(), - LHS.isVolatileQualified()); - } else { - // Handle member function pointers; other aggregates shouldn't get this far. - CGF.EmitAggExpr(RhsExpr, LHS.getAddress(), LHS.isVolatileQualified()); - } -} - -/// EmitCtorPrologue - This routine generates necessary code to initialize -/// base classes and non-static data members belonging to this constructor. -/// FIXME: This needs to take a CXXCtorType. -void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, - CXXCtorType CtorType) { - const CXXRecordDecl *ClassDecl = CD->getParent(); - - // FIXME: Add vbase initialization - - for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(), - E = CD->init_end(); - B != E; ++B) { - CXXBaseOrMemberInitializer *Member = (*B); - - assert(LiveTemporaries.empty() && - "Should not have any live temporaries at initializer start!"); - - if (Member->isBaseInitializer()) - EmitBaseInitializer(*this, ClassDecl, Member, CtorType); - else - EmitMemberInitializer(*this, ClassDecl, Member); - - // Pop any live temporaries that the initializers might have pushed. - while (!LiveTemporaries.empty()) - PopCXXTemporary(); + = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); + uint64_t Offset = Layout.getVBaseClassOffset(BaseClassDecl); + InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints, + ThisPtr, Offset); } - InitializeVtablePtrs(ClassDecl); + // Store address points for non-virtual bases and current class + InitializeVtablePtrsRecursive(ClassDecl, Vtable, AddressPoints, ThisPtr, 0); } -void CodeGenFunction::InitializeVtablePtrs(const CXXRecordDecl *ClassDecl) { +void CodeGenFunction::InitializeVtablePtrsRecursive( + const CXXRecordDecl *ClassDecl, + llvm::Constant *Vtable, + CodeGenModule::AddrSubMap_t& AddressPoints, + llvm::Value *ThisPtr, + uint64_t Offset) { if (!ClassDecl->isDynamicClass()) return; - - // Initialize the vtable pointer. - // FIXME: This needs to initialize secondary vtable pointers too. - llvm::Value *ThisPtr = LoadCXXThis(); - llvm::Constant *Vtable = CGM.getVtableInfo().getVtable(ClassDecl); - uint64_t AddressPoint = CGM.getVtableInfo().getVtableAddressPoint(ClassDecl); - - llvm::Value *VtableAddressPoint = - Builder.CreateConstInBoundsGEP2_64(Vtable, 0, AddressPoint); - - llvm::Value *VtableField = - Builder.CreateBitCast(ThisPtr, - VtableAddressPoint->getType()->getPointerTo()); - - Builder.CreateStore(VtableAddressPoint, VtableField); -} - -/// EmitDtorEpilogue - Emit all code that comes at the end of class's -/// destructor. This is to call destructors on members and base classes -/// in reverse order of their construction. -/// FIXME: This needs to take a CXXDtorType. -void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD, - CXXDtorType DtorType) { - assert(!DD->isTrivial() && - "Should not emit dtor epilogue for trivial dtor!"); - - const CXXRecordDecl *ClassDecl = DD->getParent(); - - // Collect the fields. - llvm::SmallVector<const FieldDecl *, 16> FieldDecls; - for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), - E = ClassDecl->field_end(); I != E; ++I) { - const FieldDecl *Field = *I; - - QualType FieldType = getContext().getCanonicalType(Field->getType()); - FieldType = getContext().getBaseElementType(FieldType); - - const RecordType *RT = FieldType->getAs<RecordType>(); - if (!RT) - continue; - - CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); - if (FieldClassDecl->hasTrivialDestructor()) - continue; - - FieldDecls.push_back(Field); - } - - // Now destroy the fields. - for (size_t i = FieldDecls.size(); i > 0; --i) { - const FieldDecl *Field = FieldDecls[i - 1]; - - QualType FieldType = Field->getType(); - const ConstantArrayType *Array = - getContext().getAsConstantArrayType(FieldType); - if (Array) - FieldType = getContext().getBaseElementType(FieldType); - - const RecordType *RT = FieldType->getAs<RecordType>(); - CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); - - llvm::Value *ThisPtr = LoadCXXThis(); - - LValue LHS = EmitLValueForField(ThisPtr, Field, - /*isUnion=*/false, - // FIXME: Qualifiers? - /*CVRQualifiers=*/0); - if (Array) { - const llvm::Type *BasePtr = ConvertType(FieldType); - BasePtr = llvm::PointerType::getUnqual(BasePtr); - llvm::Value *BaseAddrPtr = - Builder.CreateBitCast(LHS.getAddress(), BasePtr); - EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()), - Array, BaseAddrPtr); - } else - EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), - Dtor_Complete, LHS.getAddress()); - } - - // Destroy non-virtual bases. - for (CXXRecordDecl::reverse_base_class_const_iterator I = - ClassDecl->bases_rbegin(), E = ClassDecl->bases_rend(); I != E; ++I) { + // Store address points for non-virtual bases + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl); + for (CXXRecordDecl::base_class_const_iterator I = + ClassDecl->bases_begin(), E = ClassDecl->bases_end(); I != E; ++I) { const CXXBaseSpecifier &Base = *I; - - // Ignore virtual bases. if (Base.isVirtual()) continue; - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); - - // Ignore trivial destructors. - if (BaseClassDecl->hasTrivialDestructor()) - continue; - const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext()); - - llvm::Value *V = GetAddressOfBaseClass(LoadCXXThis(), - ClassDecl, BaseClassDecl, - /*NullCheckValue=*/false); - EmitCXXDestructorCall(D, Dtor_Base, V); + uint64_t NewOffset = Offset + Layout.getBaseClassOffset(BaseClassDecl); + InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints, + ThisPtr, NewOffset); } - // If we're emitting a base destructor, we don't want to emit calls to the - // virtual bases. - if (DtorType == Dtor_Base) - return; - - // Handle virtual bases. - for (CXXRecordDecl::reverse_base_class_const_iterator I = - ClassDecl->vbases_rbegin(), E = ClassDecl->vbases_rend(); I != E; ++I) { - const CXXBaseSpecifier &Base = *I; - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); - - // Ignore trivial destructors. - if (BaseClassDecl->hasTrivialDestructor()) - continue; - const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext()); - llvm::Value *V = GetAddressOfBaseClass(LoadCXXThis(), - ClassDecl, BaseClassDecl, - /*NullCheckValue=*/false); - EmitCXXDestructorCall(D, Dtor_Base, V); - } - - // If we have a deleting destructor, emit a call to the delete operator. - if (DtorType == Dtor_Deleting) { - assert(DD->getOperatorDelete() && - "operator delete missing - EmitDtorEpilogue"); - EmitDeleteCall(DD->getOperatorDelete(), LoadCXXThis(), - getContext().getTagDeclType(ClassDecl)); - } -} - -void CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, - llvm::Function *Fn, - const FunctionArgList &Args) { - assert(!Dtor->getParent()->hasUserDeclaredDestructor() && - "SynthesizeDefaultDestructor - destructor has user declaration"); + // Compute the address point + assert(AddressPoints.count(std::make_pair(ClassDecl, Offset)) && + "Missing address point for class"); + uint64_t AddressPoint = AddressPoints[std::make_pair(ClassDecl, Offset)]; + llvm::Value *VtableAddressPoint = + Builder.CreateConstInBoundsGEP2_64(Vtable, 0, AddressPoint); - StartFunction(GlobalDecl(Dtor, DtorType), Dtor->getResultType(), Fn, Args, - SourceLocation()); + // Compute the address to store the address point + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); + llvm::Value *VtableField = Builder.CreateBitCast(ThisPtr, Int8PtrTy); + VtableField = Builder.CreateConstInBoundsGEP1_64(VtableField, Offset/8); + const llvm::Type *AddressPointPtrTy = + VtableAddressPoint->getType()->getPointerTo(); + VtableField = Builder.CreateBitCast(VtableField, AddressPointPtrTy); - EmitDtorEpilogue(Dtor, DtorType); - FinishFunction(); + // Store address point + Builder.CreateStore(VtableAddressPoint, VtableField); } + diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 4856f54..2dda0b8 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -346,6 +346,7 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr, /// destination type; the upper bits of the src will be lost. static void CreateCoercedStore(llvm::Value *Src, llvm::Value *DstPtr, + bool DstIsVolatile, CodeGenFunction &CGF) { const llvm::Type *SrcTy = Src->getType(); const llvm::Type *DstTy = @@ -359,7 +360,7 @@ static void CreateCoercedStore(llvm::Value *Src, llvm::Value *Casted = CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy)); // FIXME: Use better alignment / avoid requiring aligned store. - CGF.Builder.CreateStore(Src, Casted)->setAlignment(1); + CGF.Builder.CreateStore(Src, Casted, DstIsVolatile)->setAlignment(1); } else { // Otherwise do coercion through memory. This is stupid, but // simple. @@ -377,7 +378,7 @@ static void CreateCoercedStore(llvm::Value *Src, llvm::LoadInst *Load = CGF.Builder.CreateLoad(Casted); // FIXME: Use better alignment / avoid requiring aligned load. Load->setAlignment(1); - CGF.Builder.CreateStore(Load, DstPtr); + CGF.Builder.CreateStore(Load, DstPtr, DstIsVolatile); } } @@ -732,7 +733,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // result in a new alloca anyway, so we could just store into that // directly if we broke the abstraction down more. llvm::Value *V = CreateTempAlloca(ConvertTypeForMem(Ty), "coerce"); - CreateCoercedStore(AI, V, *this); + CreateCoercedStore(AI, V, /*DestIsVolatile=*/false, *this); // Match to what EmitParmDecl is expecting for this type. if (!CodeGenFunction::hasAggregateLLVMType(Ty)) { V = EmitLoadOfScalar(V, false, Ty); @@ -809,6 +810,7 @@ RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) { RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *Callee, + ReturnValueSlot ReturnValue, const CallArgList &CallArgs, const Decl *TargetDecl) { // FIXME: We no longer need the types from CallArgs; lift up and simplify. @@ -821,9 +823,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If the call returns a temporary with struct return, create a temporary - // alloca to hold the result. - if (CGM.ReturnTypeUsesSret(CallInfo)) - Args.push_back(CreateTempAlloca(ConvertTypeForMem(RetTy))); + // alloca to hold the result, unless one is given to us. + if (CGM.ReturnTypeUsesSret(CallInfo)) { + llvm::Value *Value = ReturnValue.getValue(); + if (!Value) + Value = CreateTempAlloca(ConvertTypeForMem(RetTy)); + Args.push_back(Value); + } assert(CallInfo.arg_size() == CallArgs.size() && "Mismatch between function signature & arguments."); @@ -972,9 +978,15 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, return RValue::getComplex(std::make_pair(Real, Imag)); } if (CodeGenFunction::hasAggregateLLVMType(RetTy)) { - llvm::Value *V = CreateTempAlloca(ConvertTypeForMem(RetTy), "agg.tmp"); - Builder.CreateStore(CI, V); - return RValue::getAggregate(V); + llvm::Value *DestPtr = ReturnValue.getValue(); + bool DestIsVolatile = ReturnValue.isVolatile(); + + if (!DestPtr) { + DestPtr = CreateTempAlloca(ConvertTypeForMem(RetTy), "agg.tmp"); + DestIsVolatile = false; + } + Builder.CreateStore(CI, DestPtr, DestIsVolatile); + return RValue::getAggregate(DestPtr); } return RValue::get(CI); @@ -984,14 +996,20 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, return GetUndefRValue(RetTy); case ABIArgInfo::Coerce: { - // FIXME: Avoid the conversion through memory if possible. - llvm::Value *V = CreateTempAlloca(ConvertTypeForMem(RetTy), "coerce"); - CreateCoercedStore(CI, V, *this); + llvm::Value *DestPtr = ReturnValue.getValue(); + bool DestIsVolatile = ReturnValue.isVolatile(); + + if (!DestPtr) { + DestPtr = CreateTempAlloca(ConvertTypeForMem(RetTy), "coerce"); + DestIsVolatile = false; + } + + CreateCoercedStore(CI, DestPtr, DestIsVolatile, *this); if (RetTy->isAnyComplexType()) - return RValue::getComplex(LoadComplexFromAddr(V, false)); + return RValue::getComplex(LoadComplexFromAddr(DestPtr, false)); if (CodeGenFunction::hasAggregateLLVMType(RetTy)) - return RValue::getAggregate(V); - return RValue::get(EmitLoadOfScalar(V, false, RetTy)); + return RValue::getAggregate(DestPtr); + return RValue::get(EmitLoadOfScalar(DestPtr, false, RetTy)); } case ABIArgInfo::Expand: diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h index ebf801d..427ab5f 100644 --- a/lib/CodeGen/CGCall.h +++ b/lib/CodeGen/CGCall.h @@ -15,7 +15,8 @@ #ifndef CLANG_CODEGEN_CGCALL_H #define CLANG_CODEGEN_CGCALL_H -#include <llvm/ADT/FoldingSet.h> +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Value.h" #include "clang/AST/Type.h" #include "CGValue.h" @@ -123,6 +124,23 @@ namespace CodeGen { begin->Profile(ID); } }; + + /// ReturnValueSlot - Contains the address where the return value of a + /// function can be stored, and whether the address is volatile or not. + class ReturnValueSlot { + llvm::PointerIntPair<llvm::Value *, 1, bool> Value; + + public: + ReturnValueSlot() {} + ReturnValueSlot(llvm::Value *Value, bool IsVolatile) + : Value(Value, IsVolatile) {} + + bool isNull() const { return !getValue(); } + + bool isVolatile() const { return Value.getInt(); } + llvm::Value *getValue() const { return Value.getPointer(); } + }; + } // end namespace CodeGen } // end namespace clang diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index fd2afe7..953b8c8 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -269,3 +269,778 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value, return Value; } + +/// EmitClassAggrMemberwiseCopy - This routine generates code to copy a class +/// array of objects from SrcValue to DestValue. Copying can be either a bitwise +/// copy or via a copy constructor call. +// FIXME. Consolidate this with EmitCXXAggrConstructorCall. +void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest, + llvm::Value *Src, + const ArrayType *Array, + const CXXRecordDecl *BaseClassDecl, + QualType Ty) { + const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); + assert(CA && "VLA cannot be copied over"); + bool BitwiseCopy = BaseClassDecl->hasTrivialCopyConstructor(); + + // Create a temporary for the loop index and initialize it with 0. + llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), + "loop.index"); + llvm::Value* zeroConstant = + llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); + Builder.CreateStore(zeroConstant, IndexPtr); + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); + llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); + + EmitBlock(CondBlock); + + llvm::BasicBlock *ForBody = createBasicBlock("for.body"); + // Generate: if (loop-index < number-of-elements fall to the loop body, + // otherwise, go to the block after the for-loop. + uint64_t NumElements = getContext().getConstantArrayElementCount(CA); + llvm::Value * NumElementsPtr = + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); + llvm::Value *Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, + "isless"); + // If the condition is true, execute the body. + Builder.CreateCondBr(IsLess, ForBody, AfterFor); + + EmitBlock(ForBody); + llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); + // Inside the loop body, emit the constructor call on the array element. + Counter = Builder.CreateLoad(IndexPtr); + Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); + Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); + if (BitwiseCopy) + EmitAggregateCopy(Dest, Src, Ty); + else if (CXXConstructorDecl *BaseCopyCtor = + BaseClassDecl->getCopyConstructor(getContext(), 0)) { + llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, + Ctor_Complete); + CallArgList CallArgs; + // Push the this (Dest) ptr. + CallArgs.push_back(std::make_pair(RValue::get(Dest), + BaseCopyCtor->getThisType(getContext()))); + + // Push the Src ptr. + CallArgs.push_back(std::make_pair(RValue::get(Src), + BaseCopyCtor->getParamDecl(0)->getType())); + QualType ResultType = + BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType(); + EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), + Callee, ReturnValueSlot(), CallArgs, BaseCopyCtor); + } + EmitBlock(ContinueBlock); + + // Emit the increment of the loop counter. + llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); + Counter = Builder.CreateLoad(IndexPtr); + NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); + Builder.CreateStore(NextVal, IndexPtr); + + // Finally, branch back up to the condition for the next iteration. + EmitBranch(CondBlock); + + // Emit the fall-through block. + EmitBlock(AfterFor, true); +} + +/// EmitClassAggrCopyAssignment - This routine generates code to assign a class +/// array of objects from SrcValue to DestValue. Assignment can be either a +/// bitwise assignment or via a copy assignment operator function call. +/// FIXME. This can be consolidated with EmitClassAggrMemberwiseCopy +void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest, + llvm::Value *Src, + const ArrayType *Array, + const CXXRecordDecl *BaseClassDecl, + QualType Ty) { + const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); + assert(CA && "VLA cannot be asssigned"); + bool BitwiseAssign = BaseClassDecl->hasTrivialCopyAssignment(); + + // Create a temporary for the loop index and initialize it with 0. + llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), + "loop.index"); + llvm::Value* zeroConstant = + llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); + Builder.CreateStore(zeroConstant, IndexPtr); + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); + llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); + + EmitBlock(CondBlock); + + llvm::BasicBlock *ForBody = createBasicBlock("for.body"); + // Generate: if (loop-index < number-of-elements fall to the loop body, + // otherwise, go to the block after the for-loop. + uint64_t NumElements = getContext().getConstantArrayElementCount(CA); + llvm::Value * NumElementsPtr = + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); + llvm::Value *Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, + "isless"); + // If the condition is true, execute the body. + Builder.CreateCondBr(IsLess, ForBody, AfterFor); + + EmitBlock(ForBody); + llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); + // Inside the loop body, emit the assignment operator call on array element. + Counter = Builder.CreateLoad(IndexPtr); + Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); + Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); + const CXXMethodDecl *MD = 0; + if (BitwiseAssign) + EmitAggregateCopy(Dest, Src, Ty); + else { + bool hasCopyAssign = BaseClassDecl->hasConstCopyAssignment(getContext(), + MD); + assert(hasCopyAssign && "EmitClassAggrCopyAssignment - No user assign"); + (void)hasCopyAssign; + const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); + const llvm::Type *LTy = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy); + + CallArgList CallArgs; + // Push the this (Dest) ptr. + CallArgs.push_back(std::make_pair(RValue::get(Dest), + MD->getThisType(getContext()))); + + // Push the Src ptr. + CallArgs.push_back(std::make_pair(RValue::get(Src), + MD->getParamDecl(0)->getType())); + QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType(); + EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), + Callee, ReturnValueSlot(), CallArgs, MD); + } + EmitBlock(ContinueBlock); + + // Emit the increment of the loop counter. + llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); + Counter = Builder.CreateLoad(IndexPtr); + NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); + Builder.CreateStore(NextVal, IndexPtr); + + // Finally, branch back up to the condition for the next iteration. + EmitBranch(CondBlock); + + // Emit the fall-through block. + EmitBlock(AfterFor, true); +} + +/// EmitClassMemberwiseCopy - This routine generates code to copy a class +/// object from SrcValue to DestValue. Copying can be either a bitwise copy +/// or via a copy constructor call. +void CodeGenFunction::EmitClassMemberwiseCopy( + llvm::Value *Dest, llvm::Value *Src, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl, QualType Ty) { + if (ClassDecl) { + Dest = GetAddressOfBaseClass(Dest, ClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + Src = GetAddressOfBaseClass(Src, ClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + } + if (BaseClassDecl->hasTrivialCopyConstructor()) { + EmitAggregateCopy(Dest, Src, Ty); + return; + } + + if (CXXConstructorDecl *BaseCopyCtor = + BaseClassDecl->getCopyConstructor(getContext(), 0)) { + llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, + Ctor_Complete); + CallArgList CallArgs; + // Push the this (Dest) ptr. + CallArgs.push_back(std::make_pair(RValue::get(Dest), + BaseCopyCtor->getThisType(getContext()))); + + // Push the Src ptr. + CallArgs.push_back(std::make_pair(RValue::get(Src), + BaseCopyCtor->getParamDecl(0)->getType())); + QualType ResultType = + BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType(); + EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), + Callee, ReturnValueSlot(), CallArgs, BaseCopyCtor); + } +} + +/// EmitClassCopyAssignment - This routine generates code to copy assign a class +/// object from SrcValue to DestValue. Assignment can be either a bitwise +/// assignment of via an assignment operator call. +// FIXME. Consolidate this with EmitClassMemberwiseCopy as they share a lot. +void CodeGenFunction::EmitClassCopyAssignment( + llvm::Value *Dest, llvm::Value *Src, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl, + QualType Ty) { + if (ClassDecl) { + Dest = GetAddressOfBaseClass(Dest, ClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + Src = GetAddressOfBaseClass(Src, ClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + } + if (BaseClassDecl->hasTrivialCopyAssignment()) { + EmitAggregateCopy(Dest, Src, Ty); + return; + } + + const CXXMethodDecl *MD = 0; + bool ConstCopyAssignOp = BaseClassDecl->hasConstCopyAssignment(getContext(), + MD); + assert(ConstCopyAssignOp && "EmitClassCopyAssignment - missing copy assign"); + (void)ConstCopyAssignOp; + + const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); + const llvm::Type *LTy = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy); + + CallArgList CallArgs; + // Push the this (Dest) ptr. + CallArgs.push_back(std::make_pair(RValue::get(Dest), + MD->getThisType(getContext()))); + + // Push the Src ptr. + CallArgs.push_back(std::make_pair(RValue::get(Src), + MD->getParamDecl(0)->getType())); + QualType ResultType = + MD->getType()->getAs<FunctionType>()->getResultType(); + EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), + Callee, ReturnValueSlot(), CallArgs, MD); +} + +/// SynthesizeDefaultConstructor - synthesize a default constructor +void +CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor, + CXXCtorType Type, + llvm::Function *Fn, + const FunctionArgList &Args) { + assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor"); + StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args, + SourceLocation()); + EmitCtorPrologue(Ctor, Type); + FinishFunction(); +} + +/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a +/// copy constructor, in accordance with section 12.8 (p7 and p8) of C++03 +/// The implicitly-defined copy constructor for class X performs a memberwise +/// copy of its subobjects. The order of copying is the same as the order of +/// initialization of bases and members in a user-defined constructor +/// Each subobject is copied in the manner appropriate to its type: +/// if the subobject is of class type, the copy constructor for the class is +/// used; +/// if the subobject is an array, each element is copied, in the manner +/// appropriate to the element type; +/// if the subobject is of scalar type, the built-in assignment operator is +/// used. +/// Virtual base class subobjects shall be copied only once by the +/// implicitly-defined copy constructor + +void +CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, + CXXCtorType Type, + llvm::Function *Fn, + const FunctionArgList &Args) { + const CXXRecordDecl *ClassDecl = Ctor->getParent(); + assert(!ClassDecl->hasUserDeclaredCopyConstructor() && + "SynthesizeCXXCopyConstructor - copy constructor has definition already"); + assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor"); + StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args, + SourceLocation()); + + FunctionArgList::const_iterator i = Args.begin(); + const VarDecl *ThisArg = i->first; + llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg); + llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this"); + const VarDecl *SrcArg = (i+1)->first; + llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg); + llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj); + + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + // FIXME. copy constrution of virtual base NYI + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + EmitClassMemberwiseCopy(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl, + Base->getType()); + } + + for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), + E = ClassDecl->field_end(); I != E; ++I) { + const FieldDecl *Field = *I; + + QualType FieldType = getContext().getCanonicalType(Field->getType()); + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = getContext().getBaseElementType(FieldType); + + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); + LValue RHS = EmitLValueForField(LoadOfSrc, Field, false, 0); + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *DestBaseAddrPtr = + Builder.CreateBitCast(LHS.getAddress(), BasePtr); + llvm::Value *SrcBaseAddrPtr = + Builder.CreateBitCast(RHS.getAddress(), BasePtr); + EmitClassAggrMemberwiseCopy(DestBaseAddrPtr, SrcBaseAddrPtr, Array, + FieldClassDecl, FieldType); + } + else + EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(), + 0 /*ClassDecl*/, FieldClassDecl, FieldType); + continue; + } + + if (Field->getType()->isReferenceType()) { + unsigned FieldIndex = CGM.getTypes().getLLVMFieldNo(Field); + + llvm::Value *LHS = Builder.CreateStructGEP(LoadOfThis, FieldIndex, + "lhs.ref"); + + llvm::Value *RHS = Builder.CreateStructGEP(LoadOfThis, FieldIndex, + "rhs.ref"); + + // Load the value in RHS. + RHS = Builder.CreateLoad(RHS); + + // And store it in the LHS + Builder.CreateStore(RHS, LHS); + + continue; + } + // Do a built-in assignment of scalar data members. + LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); + LValue RHS = EmitLValueForField(LoadOfSrc, Field, false, 0); + + if (!hasAggregateLLVMType(Field->getType())) { + RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType()); + EmitStoreThroughLValue(RVRHS, LHS, Field->getType()); + } else if (Field->getType()->isAnyComplexType()) { + ComplexPairTy Pair = LoadComplexFromAddr(RHS.getAddress(), + RHS.isVolatileQualified()); + StoreComplexToAddr(Pair, LHS.getAddress(), LHS.isVolatileQualified()); + } else { + EmitAggregateCopy(LHS.getAddress(), RHS.getAddress(), Field->getType()); + } + } + + InitializeVtablePtrs(ClassDecl); + FinishFunction(); +} + +/// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator. +/// Before the implicitly-declared copy assignment operator for a class is +/// implicitly defined, all implicitly- declared copy assignment operators for +/// its direct base classes and its nonstatic data members shall have been +/// implicitly defined. [12.8-p12] +/// The implicitly-defined copy assignment operator for class X performs +/// memberwise assignment of its subob- jects. The direct base classes of X are +/// assigned first, in the order of their declaration in +/// the base-specifier-list, and then the immediate nonstatic data members of X +/// are assigned, in the order in which they were declared in the class +/// definition.Each subobject is assigned in the manner appropriate to its type: +/// if the subobject is of class type, the copy assignment operator for the +/// class is used (as if by explicit qualification; that is, ignoring any +/// possible virtual overriding functions in more derived classes); +/// +/// if the subobject is an array, each element is assigned, in the manner +/// appropriate to the element type; +/// +/// if the subobject is of scalar type, the built-in assignment operator is +/// used. +void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD, + llvm::Function *Fn, + const FunctionArgList &Args) { + + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); + assert(!ClassDecl->hasUserDeclaredCopyAssignment() && + "SynthesizeCXXCopyAssignment - copy assignment has user declaration"); + StartFunction(CD, CD->getResultType(), Fn, Args, SourceLocation()); + + FunctionArgList::const_iterator i = Args.begin(); + const VarDecl *ThisArg = i->first; + llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg); + llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this"); + const VarDecl *SrcArg = (i+1)->first; + llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg); + llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj); + + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + // FIXME. copy assignment of virtual base NYI + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + EmitClassCopyAssignment(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl, + Base->getType()); + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + QualType FieldType = getContext().getCanonicalType((*Field)->getType()); + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = getContext().getBaseElementType(FieldType); + + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); + LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *DestBaseAddrPtr = + Builder.CreateBitCast(LHS.getAddress(), BasePtr); + llvm::Value *SrcBaseAddrPtr = + Builder.CreateBitCast(RHS.getAddress(), BasePtr); + EmitClassAggrCopyAssignment(DestBaseAddrPtr, SrcBaseAddrPtr, Array, + FieldClassDecl, FieldType); + } + else + EmitClassCopyAssignment(LHS.getAddress(), RHS.getAddress(), + 0 /*ClassDecl*/, FieldClassDecl, FieldType); + continue; + } + // Do a built-in assignment of scalar data members. + LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); + LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); + if (!hasAggregateLLVMType(Field->getType())) { + RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType()); + EmitStoreThroughLValue(RVRHS, LHS, Field->getType()); + } else if (Field->getType()->isAnyComplexType()) { + ComplexPairTy Pair = LoadComplexFromAddr(RHS.getAddress(), + RHS.isVolatileQualified()); + StoreComplexToAddr(Pair, LHS.getAddress(), LHS.isVolatileQualified()); + } else { + EmitAggregateCopy(LHS.getAddress(), RHS.getAddress(), Field->getType()); + } + } + + // return *this; + Builder.CreateStore(LoadOfThis, ReturnValue); + + FinishFunction(); +} + +static void EmitBaseInitializer(CodeGenFunction &CGF, + const CXXRecordDecl *ClassDecl, + CXXBaseOrMemberInitializer *BaseInit, + CXXCtorType CtorType) { + assert(BaseInit->isBaseInitializer() && + "Must have base initializer!"); + + llvm::Value *ThisPtr = CGF.LoadCXXThis(); + + const Type *BaseType = BaseInit->getBaseClass(); + CXXRecordDecl *BaseClassDecl = + cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); + + // FIXME: This method of determining whether a base is virtual is ridiculous; + // it should be part of BaseInit. + bool isBaseVirtual = false; + for (CXXRecordDecl::base_class_const_iterator I = ClassDecl->vbases_begin(), + E = ClassDecl->vbases_end(); I != E; ++I) + if (I->getType()->getAs<RecordType>()->getDecl() == BaseClassDecl) { + isBaseVirtual = true; + break; + } + + // The base constructor doesn't construct virtual bases. + if (CtorType == Ctor_Base && isBaseVirtual) + return; + + // Compute the offset to the base; we do this directly instead of using + // GetAddressOfBaseClass because the class doesn't have a vtable pointer + // at this point. + // FIXME: This could be refactored back into GetAddressOfBaseClass if it took + // an extra parameter for whether the derived class is the complete object + // class. + const ASTRecordLayout &Layout = + CGF.getContext().getASTRecordLayout(ClassDecl); + uint64_t Offset; + if (isBaseVirtual) + Offset = Layout.getVBaseClassOffset(BaseClassDecl); + else + Offset = Layout.getBaseClassOffset(BaseClassDecl); + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); + const llvm::Type *BaseClassType = CGF.ConvertType(QualType(BaseType, 0)); + llvm::Value *V = CGF.Builder.CreateBitCast(ThisPtr, Int8PtrTy); + V = CGF.Builder.CreateConstInBoundsGEP1_64(V, Offset/8); + V = CGF.Builder.CreateBitCast(V, BaseClassType->getPointerTo()); + + // FIXME: This should always use Ctor_Base as the ctor type! (But that + // causes crashes in tests.) + CGF.EmitCXXConstructorCall(BaseInit->getConstructor(), + CtorType, V, + BaseInit->const_arg_begin(), + BaseInit->const_arg_end()); +} + +static void EmitMemberInitializer(CodeGenFunction &CGF, + const CXXRecordDecl *ClassDecl, + CXXBaseOrMemberInitializer *MemberInit) { + assert(MemberInit->isMemberInitializer() && + "Must have member initializer!"); + + // non-static data member initializers. + FieldDecl *Field = MemberInit->getMember(); + QualType FieldType = CGF.getContext().getCanonicalType(Field->getType()); + + llvm::Value *ThisPtr = CGF.LoadCXXThis(); + LValue LHS; + if (FieldType->isReferenceType()) { + // FIXME: This is really ugly; should be refactored somehow + unsigned idx = CGF.CGM.getTypes().getLLVMFieldNo(Field); + llvm::Value *V = CGF.Builder.CreateStructGEP(ThisPtr, idx, "tmp"); + assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs"); + LHS = LValue::MakeAddr(V, CGF.MakeQualifiers(FieldType)); + } else { + LHS = CGF.EmitLValueForField(ThisPtr, Field, ClassDecl->isUnion(), 0); + } + + // If we are initializing an anonymous union field, drill down to the field. + if (MemberInit->getAnonUnionMember()) { + Field = MemberInit->getAnonUnionMember(); + LHS = CGF.EmitLValueForField(LHS.getAddress(), Field, + /*IsUnion=*/true, 0); + FieldType = Field->getType(); + } + + // If the field is an array, branch based on the element type. + const ConstantArrayType *Array = + CGF.getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = CGF.getContext().getBaseElementType(FieldType); + + // We lose the constructor for anonymous union members, so handle them + // explicitly. + // FIXME: This is somwhat ugly. + if (MemberInit->getAnonUnionMember() && FieldType->getAs<RecordType>()) { + if (MemberInit->getNumArgs()) + CGF.EmitAggExpr(*MemberInit->arg_begin(), LHS.getAddress(), + LHS.isVolatileQualified()); + else + CGF.EmitAggregateClear(LHS.getAddress(), Field->getType()); + return; + } + + if (FieldType->getAs<RecordType>()) { + assert(MemberInit->getConstructor() && + "EmitCtorPrologue - no constructor to initialize member"); + if (Array) { + const llvm::Type *BasePtr = CGF.ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = + CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr); + CGF.EmitCXXAggrConstructorCall(MemberInit->getConstructor(), + Array, BaseAddrPtr, + MemberInit->const_arg_begin(), + MemberInit->const_arg_end()); + } + else + CGF.EmitCXXConstructorCall(MemberInit->getConstructor(), + Ctor_Complete, LHS.getAddress(), + MemberInit->const_arg_begin(), + MemberInit->const_arg_end()); + return; + } + + assert(MemberInit->getNumArgs() == 1 && "Initializer count must be 1 only"); + Expr *RhsExpr = *MemberInit->arg_begin(); + RValue RHS; + if (FieldType->isReferenceType()) { + RHS = CGF.EmitReferenceBindingToExpr(RhsExpr, FieldType, + /*IsInitializer=*/true); + CGF.EmitStoreThroughLValue(RHS, LHS, FieldType); + } else if (Array) { + CGF.EmitMemSetToZero(LHS.getAddress(), Field->getType()); + } else if (!CGF.hasAggregateLLVMType(RhsExpr->getType())) { + RHS = RValue::get(CGF.EmitScalarExpr(RhsExpr, true)); + CGF.EmitStoreThroughLValue(RHS, LHS, FieldType); + } else if (RhsExpr->getType()->isAnyComplexType()) { + CGF.EmitComplexExprIntoAddr(RhsExpr, LHS.getAddress(), + LHS.isVolatileQualified()); + } else { + // Handle member function pointers; other aggregates shouldn't get this far. + CGF.EmitAggExpr(RhsExpr, LHS.getAddress(), LHS.isVolatileQualified()); + } +} + +/// EmitCtorPrologue - This routine generates necessary code to initialize +/// base classes and non-static data members belonging to this constructor. +/// FIXME: This needs to take a CXXCtorType. +void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, + CXXCtorType CtorType) { + const CXXRecordDecl *ClassDecl = CD->getParent(); + + // FIXME: Add vbase initialization + + for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(), + E = CD->init_end(); + B != E; ++B) { + CXXBaseOrMemberInitializer *Member = (*B); + + assert(LiveTemporaries.empty() && + "Should not have any live temporaries at initializer start!"); + + if (Member->isBaseInitializer()) + EmitBaseInitializer(*this, ClassDecl, Member, CtorType); + else + EmitMemberInitializer(*this, ClassDecl, Member); + + // Pop any live temporaries that the initializers might have pushed. + while (!LiveTemporaries.empty()) + PopCXXTemporary(); + } + + InitializeVtablePtrs(ClassDecl); +} + +/// EmitDtorEpilogue - Emit all code that comes at the end of class's +/// destructor. This is to call destructors on members and base classes +/// in reverse order of their construction. +/// FIXME: This needs to take a CXXDtorType. +void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD, + CXXDtorType DtorType) { + assert(!DD->isTrivial() && + "Should not emit dtor epilogue for trivial dtor!"); + + const CXXRecordDecl *ClassDecl = DD->getParent(); + + // Collect the fields. + llvm::SmallVector<const FieldDecl *, 16> FieldDecls; + for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), + E = ClassDecl->field_end(); I != E; ++I) { + const FieldDecl *Field = *I; + + QualType FieldType = getContext().getCanonicalType(Field->getType()); + FieldType = getContext().getBaseElementType(FieldType); + + const RecordType *RT = FieldType->getAs<RecordType>(); + if (!RT) + continue; + + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (FieldClassDecl->hasTrivialDestructor()) + continue; + + FieldDecls.push_back(Field); + } + + // Now destroy the fields. + for (size_t i = FieldDecls.size(); i > 0; --i) { + const FieldDecl *Field = FieldDecls[i - 1]; + + QualType FieldType = Field->getType(); + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = getContext().getBaseElementType(FieldType); + + const RecordType *RT = FieldType->getAs<RecordType>(); + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + + llvm::Value *ThisPtr = LoadCXXThis(); + + LValue LHS = EmitLValueForField(ThisPtr, Field, + /*isUnion=*/false, + // FIXME: Qualifiers? + /*CVRQualifiers=*/0); + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = + Builder.CreateBitCast(LHS.getAddress(), BasePtr); + EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()), + Array, BaseAddrPtr); + } else + EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), + Dtor_Complete, LHS.getAddress()); + } + + // Destroy non-virtual bases. + for (CXXRecordDecl::reverse_base_class_const_iterator I = + ClassDecl->bases_rbegin(), E = ClassDecl->bases_rend(); I != E; ++I) { + const CXXBaseSpecifier &Base = *I; + + // Ignore virtual bases. + if (Base.isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); + + // Ignore trivial destructors. + if (BaseClassDecl->hasTrivialDestructor()) + continue; + const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext()); + + llvm::Value *V = GetAddressOfBaseClass(LoadCXXThis(), + ClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + EmitCXXDestructorCall(D, Dtor_Base, V); + } + + // If we're emitting a base destructor, we don't want to emit calls to the + // virtual bases. + if (DtorType == Dtor_Base) + return; + + // Handle virtual bases. + for (CXXRecordDecl::reverse_base_class_const_iterator I = + ClassDecl->vbases_rbegin(), E = ClassDecl->vbases_rend(); I != E; ++I) { + const CXXBaseSpecifier &Base = *I; + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); + + // Ignore trivial destructors. + if (BaseClassDecl->hasTrivialDestructor()) + continue; + const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext()); + llvm::Value *V = GetAddressOfBaseClass(LoadCXXThis(), + ClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + EmitCXXDestructorCall(D, Dtor_Base, V); + } + + // If we have a deleting destructor, emit a call to the delete operator. + if (DtorType == Dtor_Deleting) { + assert(DD->getOperatorDelete() && + "operator delete missing - EmitDtorEpilogue"); + EmitDeleteCall(DD->getOperatorDelete(), LoadCXXThis(), + getContext().getTagDeclType(ClassDecl)); + } +} + +void CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor, + CXXDtorType DtorType, + llvm::Function *Fn, + const FunctionArgList &Args) { + assert(!Dtor->getParent()->hasUserDeclaredDestructor() && + "SynthesizeDefaultDestructor - destructor has user declaration"); + + StartFunction(GlobalDecl(Dtor, DtorType), Dtor->getResultType(), Fn, Args, + SourceLocation()); + + EmitDtorEpilogue(Dtor, DtorType); + FinishFunction(); +} diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 2238c89..19695c8 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -123,8 +123,6 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) { CLANG_VENDOR #endif "clang " CLANG_VERSION_STRING; - bool isOptimized = LO.Optimize; - const char *Flags = ""; // FIXME: Encode command line options. // Figure out which version of the ObjC runtime we have. unsigned RuntimeVers = 0; @@ -132,11 +130,9 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) { RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1; // Create new compile unit. - return Unit = DebugFactory.CreateCompileUnit(LangTag, - AbsFileName.getLast(), - AbsFileName.getDirname(), - Producer, isMain, - isOptimized, Flags, RuntimeVers); + return Unit = DebugFactory.CreateCompileUnit( + LangTag, AbsFileName.getLast(), AbsFileName.getDirname(), Producer, isMain, + LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers); } /// CreateType - Get the Basic type from the cache or create a new @@ -834,27 +830,43 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty, 0, 0, 0, llvm::DIType(), Elements); } -static QualType CanonicalizeTypeForDebugInfo(QualType T) { - switch (T->getTypeClass()) { - default: - return T; - case Type::TemplateSpecialization: - return cast<TemplateSpecializationType>(T)->desugar(); - case Type::TypeOfExpr: { - TypeOfExprType *Ty = cast<TypeOfExprType>(T); - return CanonicalizeTypeForDebugInfo(Ty->getUnderlyingExpr()->getType()); - } - case Type::TypeOf: - return cast<TypeOfType>(T)->getUnderlyingType(); - case Type::Decltype: - return cast<DecltypeType>(T)->getUnderlyingType(); - case Type::QualifiedName: - return cast<QualifiedNameType>(T)->getNamedType(); - case Type::SubstTemplateTypeParm: - return cast<SubstTemplateTypeParmType>(T)->getReplacementType(); - case Type::Elaborated: - return cast<ElaboratedType>(T)->getUnderlyingType(); - } +static QualType UnwrapTypeForDebugInfo(QualType T) { + do { + QualType LastT = T; + switch (T->getTypeClass()) { + default: + return T; + case Type::TemplateSpecialization: + T = cast<TemplateSpecializationType>(T)->desugar(); + break; + case Type::TypeOfExpr: { + TypeOfExprType *Ty = cast<TypeOfExprType>(T); + T = Ty->getUnderlyingExpr()->getType(); + break; + } + case Type::TypeOf: + T = cast<TypeOfType>(T)->getUnderlyingType(); + break; + case Type::Decltype: + T = cast<DecltypeType>(T)->getUnderlyingType(); + break; + case Type::QualifiedName: + T = cast<QualifiedNameType>(T)->getNamedType(); + break; + case Type::SubstTemplateTypeParm: + T = cast<SubstTemplateTypeParmType>(T)->getReplacementType(); + break; + case Type::Elaborated: + T = cast<ElaboratedType>(T)->getUnderlyingType(); + break; + } + + assert(T != LastT && "Type unwrapping failed to unwrap!"); + if (T == LastT) + return T; + } while (true); + + return T; } /// getOrCreateType - Get the type from the cache or create a new @@ -864,8 +876,8 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, if (Ty.isNull()) return llvm::DIType(); - // Canonicalize the type. - Ty = CanonicalizeTypeForDebugInfo(Ty); + // Unwrap the type as needed for debug information. + Ty = UnwrapTypeForDebugInfo(Ty); // Check for existing entry. std::map<void *, llvm::WeakVH>::iterator it = @@ -891,6 +903,8 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, if (Ty.hasLocalQualifiers()) return CreateQualifiedType(Ty, Unit); + const char *Diag = 0; + // Work out details of type. switch (Ty->getTypeClass()) { #define TYPE(Class, Base) @@ -903,11 +917,8 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, // FIXME: Handle these. case Type::ExtVector: case Type::Vector: - case Type::FixedWidthInt: - return llvm::DIType(); - default: - assert(false && "Unhandled type class!"); return llvm::DIType(); + case Type::ObjCObjectPointer: return CreateType(cast<ObjCObjectPointerType>(Ty), Unit); case Type::ObjCInterface: @@ -934,7 +945,29 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, case Type::MemberPointer: return CreateType(cast<MemberPointerType>(Ty), Unit); + + case Type::TemplateSpecialization: + case Type::Elaborated: + case Type::QualifiedName: + case Type::SubstTemplateTypeParm: + case Type::TypeOfExpr: + case Type::TypeOf: + case Type::Decltype: + llvm_unreachable("type should have been unwrapped!"); + return llvm::DIType(); + + case Type::RValueReference: + // FIXME: Implement! + Diag = "rvalue references"; + break; } + + assert(Diag && "Fall through without a diagnostic?"); + unsigned DiagID = CGM.getDiags().getCustomDiagID(Diagnostic::Error, + "debug information for %0 is not yet supported"); + CGM.getDiags().Report(FullSourceLoc(), DiagID) + << Diag; + return llvm::DIType(); } /// EmitFunctionStart - Constructs the debug code for entering a function - @@ -1067,7 +1100,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag, EltTys.push_back(FieldTy); FieldOffset += FieldSize; - FType = CGM.getContext().getFixedWidthIntType(32, true); // Int32Ty; + FType = CGM.getContext().IntTy; FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); @@ -1078,7 +1111,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag, EltTys.push_back(FieldTy); FieldOffset += FieldSize; - FType = CGM.getContext().getFixedWidthIntType(32, true); // Int32Ty; + FType = CGM.getContext().IntTy; FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); @@ -1182,9 +1215,9 @@ void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag, llvm::DIScope DS(RegionStack.back()); llvm::DILocation DO(NULL); - llvm::DILocation DL = - DebugFactory.CreateLocation(Line, Column, DS, DO); - Builder.SetDebugLocation(Call, DL.getNode()); + llvm::DILocation DL = DebugFactory.CreateLocation(Line, Column, DS, DO); + + Call->setMetadata("dbg", DL.getNode()); } /// EmitDeclare - Emit local variable declaration debug info. @@ -1244,7 +1277,7 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, EltTys.push_back(FieldTy); FieldOffset += FieldSize; - FType = CGM.getContext().getFixedWidthIntType(32, true); // Int32Ty; + FType = CGM.getContext().IntTy; FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); @@ -1255,7 +1288,7 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, EltTys.push_back(FieldTy); FieldOffset += FieldSize; - FType = CGM.getContext().getFixedWidthIntType(32, true); // Int32Ty; + FType = CGM.getContext().IntTy; FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); @@ -1385,7 +1418,8 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, llvm::DILocation DO(NULL); llvm::DILocation DL = DebugFactory.CreateLocation(Line, PLoc.getColumn(), DS, DO); - Builder.SetDebugLocation(Call, DL.getNode()); + + Call->setMetadata("dbg", DL.getNode()); } void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *Decl, diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 14ee90d..602cc9e 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -15,6 +15,7 @@ #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/SourceManager.h" @@ -471,7 +472,8 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { const llvm::Type *IntPtr = llvm::IntegerType::get(VMContext, LLVMPointerWidth); llvm::Value *SizeVal = - llvm::ConstantInt::get(IntPtr, getContext().getTypeSizeInBytes(Ty)); + llvm::ConstantInt::get(IntPtr, + getContext().getTypeSizeInChars(Ty).getRaw()); const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext); if (Loc->getType() != BP) @@ -641,7 +643,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr, ConvertType(ArgTy))), getContext().getPointerType(D.getType()))); - EmitCall(Info, F, Args); + EmitCall(Info, F, ReturnValueSlot(), Args); } if (Exceptions) { EHCleanupBlock Cleanup(*this); @@ -650,7 +652,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr, ConvertType(ArgTy))), getContext().getPointerType(D.getType()))); - EmitCall(Info, F, Args); + EmitCall(Info, F, ReturnValueSlot(), Args); } } diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index b15b2e9..bd0461f 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -149,21 +149,39 @@ static void CopyObject(CodeGenFunction &CGF, const Expr *E, CGF.EmitAggExpr(E, This, false); } else if (CXXConstructorDecl *CopyCtor = RD->getCopyConstructor(CGF.getContext(), 0)) { - llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest(); + llvm::Value *CondPtr = 0; if (CGF.Exceptions) { CodeGenFunction::EHCleanupBlock Cleanup(CGF); llvm::Constant *FreeExceptionFn = getFreeExceptionFn(CGF); + llvm::BasicBlock *CondBlock = CGF.createBasicBlock("cond.free"); + llvm::BasicBlock *Cont = CGF.createBasicBlock("cont"); + CondPtr = CGF.CreateTempAlloca(llvm::Type::getInt1Ty(CGF.getLLVMContext()), + "doEHfree"); + + CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CondPtr), + CondBlock, Cont); + CGF.EmitBlock(CondBlock); + // Load the exception pointer. llvm::Value *ExceptionPtr = CGF.Builder.CreateLoad(ExceptionPtrPtr); CGF.Builder.CreateCall(FreeExceptionFn, ExceptionPtr); + + CGF.EmitBlock(Cont); } + if (CondPtr) + CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(CGF.getLLVMContext()), + CondPtr); + llvm::Value *Src = CGF.EmitLValue(E).getAddress(); - CGF.setInvokeDest(PrevLandingPad); + + if (CondPtr) + CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()), + CondPtr); llvm::BasicBlock *TerminateHandler = CGF.getTerminateHandler(); - PrevLandingPad = CGF.getInvokeDest(); + llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest(); CGF.setInvokeDest(TerminateHandler); // Stolen from EmitClassAggrMemberwiseCopy @@ -179,7 +197,7 @@ static void CopyObject(CodeGenFunction &CGF, const Expr *E, QualType ResultType = CopyCtor->getType()->getAs<FunctionType>()->getResultType(); CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(ResultType, CallArgs), - Callee, CallArgs, CopyCtor); + Callee, ReturnValueSlot(), CallArgs, CopyCtor); CGF.setInvokeDest(PrevLandingPad); } else llvm_unreachable("uncopyable object"); @@ -189,14 +207,22 @@ static void CopyObject(CodeGenFunction &CGF, const Expr *E, // CopyObject - Utility to copy an object. Calls copy constructor as necessary. // N is casted to the right type. static void CopyObject(CodeGenFunction &CGF, QualType ObjectType, - bool WasPointer, llvm::Value *E, llvm::Value *N) { + bool WasPointer, bool WasPointerReference, + llvm::Value *E, llvm::Value *N) { // Store the throw exception in the exception object. if (WasPointer || !CGF.hasAggregateLLVMType(ObjectType)) { llvm::Value *Value = E; if (!WasPointer) Value = CGF.Builder.CreateLoad(Value); const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo(0); - CGF.Builder.CreateStore(Value, CGF.Builder.CreateBitCast(N, ValuePtrTy)); + if (WasPointerReference) { + llvm::Value *Tmp = CGF.CreateTempAlloca(Value->getType(), "catch.param"); + CGF.Builder.CreateStore(Value, Tmp); + Value = Tmp; + ValuePtrTy = Value->getType()->getPointerTo(0); + } + N = CGF.Builder.CreateBitCast(N, ValuePtrTy); + CGF.Builder.CreateStore(Value, N); } else { const llvm::Type *Ty = CGF.ConvertType(ObjectType)->getPointerTo(0); const CXXRecordDecl *RD; @@ -221,7 +247,7 @@ static void CopyObject(CodeGenFunction &CGF, QualType ObjectType, QualType ResultType = CopyCtor->getType()->getAs<FunctionType>()->getResultType(); CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(ResultType, CallArgs), - Callee, CallArgs, CopyCtor); + Callee, ReturnValueSlot(), CallArgs, CopyCtor); } else llvm_unreachable("uncopyable object"); } @@ -264,7 +290,7 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { // Now throw the exception. const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); - llvm::Constant *TypeInfo = CGM.GenerateRTTI(ThrowType); + llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType); llvm::Constant *Dtor = llvm::Constant::getNullValue(Int8PtrTy); if (getInvokeDest()) { @@ -347,8 +373,9 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { for (unsigned i = 0; i < Proto->getNumExceptions(); ++i) { QualType Ty = Proto->getExceptionType(i); - llvm::Value *EHType - = CGM.GenerateRTTI(Ty.getNonReferenceType()); + QualType ExceptType + = Ty.getNonReferenceType().getUnqualifiedType(); + llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType); SelectorArgs.push_back(EHType); } if (Proto->getNumExceptions()) @@ -487,9 +514,12 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { const CXXCatchStmt *C = S.getHandler(i); VarDecl *CatchParam = C->getExceptionDecl(); if (CatchParam) { - llvm::Value *EHType - = CGM.GenerateRTTI(C->getCaughtType().getNonReferenceType()); - SelectorArgs.push_back(EHType); + // C++ [except.handle]p3 indicates that top-level cv-qualifiers + // are ignored. + QualType CaughtType = C->getCaughtType().getNonReferenceType(); + llvm::Value *EHTypeInfo + = CGM.GetAddrOfRTTIDescriptor(CaughtType.getUnqualifiedType()); + SelectorArgs.push_back(EHTypeInfo); } else { // null indicates catch all SelectorArgs.push_back(Null); @@ -541,7 +571,12 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { QualType CatchType = CatchParam->getType().getNonReferenceType(); setInvokeDest(TerminateHandler); bool WasPointer = true; - if (!CatchType.getTypePtr()->isPointerType()) { + bool WasPointerReference = false; + CatchType = CGM.getContext().getCanonicalType(CatchType); + if (CatchType.getTypePtr()->isPointerType()) { + if (isa<ReferenceType>(CatchParam->getType())) + WasPointerReference = true; + } else { if (!isa<ReferenceType>(CatchParam->getType())) WasPointer = false; CatchType = getContext().getPointerType(CatchType); @@ -552,7 +587,8 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { // cleanup doesn't start until after the ctor completes, use a decl // init? CopyObject(*this, CatchParam->getType().getNonReferenceType(), - WasPointer, ExcObject, GetAddrOfLocalVar(CatchParam)); + WasPointer, WasPointerReference, ExcObject, + GetAddrOfLocalVar(CatchParam)); setInvokeDest(MatchHandler); } diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index e6bbfa8..ab451cf 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -97,13 +97,15 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, bool IsInitializer) { bool ShouldDestroyTemporaries = false; unsigned OldNumLiveTemporaries = 0; - - if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) { - ShouldDestroyTemporaries = TE->shouldDestroyTemporaries(); + if (const CXXDefaultArgExpr *DAE = dyn_cast<CXXDefaultArgExpr>(E)) + E = DAE->getExpr(); + + if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) { + ShouldDestroyTemporaries = true; + // Keep track of the current cleanup stack depth. - if (ShouldDestroyTemporaries) - OldNumLiveTemporaries = LiveTemporaries.size(); + OldNumLiveTemporaries = LiveTemporaries.size(); E = TE->getSubExpr(); } @@ -209,6 +211,34 @@ unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx, return cast<llvm::ConstantInt>(Elts->getOperand(Idx))->getZExtValue(); } +void CodeGenFunction::EmitCheck(llvm::Value *Address, unsigned Size) { + if (!CatchUndefined) + return; + + const llvm::IntegerType *Size_tTy + = llvm::IntegerType::get(VMContext, LLVMPointerWidth); + Address = Builder.CreateBitCast(Address, PtrToInt8Ty); + + const llvm::Type *ResType[] = { + Size_tTy + }; + llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, ResType, 1); + const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( + CGM.getTypes().ConvertType(CGM.getContext().IntTy)); + // In time, people may want to control this and use a 1 here. + llvm::Value *Arg = llvm::ConstantInt::get(IntTy, 0); + llvm::Value *C = Builder.CreateCall2(F, Address, Arg); + llvm::BasicBlock *Cont = createBasicBlock(); + llvm::BasicBlock *Check = createBasicBlock(); + llvm::Value *NegativeOne = llvm::ConstantInt::get(Size_tTy, -1ULL); + Builder.CreateCondBr(Builder.CreateICmpEQ(C, NegativeOne), Cont, Check); + + EmitBlock(Check); + Builder.CreateCondBr(Builder.CreateICmpUGE(C, + llvm::ConstantInt::get(Size_tTy, Size)), + Cont, getTrapBB()); + EmitBlock(Cont); +} //===----------------------------------------------------------------------===// // LValue Expression Emission @@ -246,6 +276,13 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E, MakeQualifiers(E->getType())); } +LValue CodeGenFunction::EmitCheckedLValue(const Expr *E) { + LValue LV = EmitLValue(E); + if (!isa<DeclRefExpr>(E) && !LV.isBitfield() && LV.isSimple()) + EmitCheck(LV.getAddress(), getContext().getTypeSize(E->getType()) / 8); + return LV; +} + /// EmitLValue - Emit code to compute a designator that specifies the location /// of the expression. /// @@ -1072,8 +1109,9 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { llvm::IntegerType::get(VMContext, LLVMPointerWidth), IdxSigned, "idxprom"); + // FIXME: As llvm implements the object size checking, this can come out. if (CatchUndefined) { - if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E->getBase())) { + if (const ImplicitCastExpr *ICE=dyn_cast<ImplicitCastExpr>(E->getBase())) { if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) { if (ICE->getCastKind() == CastExpr::CK_ArrayToPointerDecay) { if (const ConstantArrayType *CAT @@ -1141,7 +1179,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { static llvm::Constant *GenerateConstantVector(llvm::LLVMContext &VMContext, llvm::SmallVector<unsigned, 4> &Elts) { - llvm::SmallVector<llvm::Constant *, 4> CElts; + llvm::SmallVector<llvm::Constant*, 4> CElts; for (unsigned i = 0, e = Elts.size(); i != e; ++i) CElts.push_back(llvm::ConstantInt::get( @@ -1152,21 +1190,37 @@ llvm::Constant *GenerateConstantVector(llvm::LLVMContext &VMContext, LValue CodeGenFunction:: EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { + const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext); + // Emit the base vector as an l-value. LValue Base; // ExtVectorElementExpr's base can either be a vector or pointer to vector. - if (!E->isArrow()) { - assert(E->getBase()->getType()->isVectorType()); - Base = EmitLValue(E->getBase()); - } else { - const PointerType *PT = E->getBase()->getType()->getAs<PointerType>(); + if (E->isArrow()) { + // If it is a pointer to a vector, emit the address and form an lvalue with + // it. llvm::Value *Ptr = EmitScalarExpr(E->getBase()); + const PointerType *PT = E->getBase()->getType()->getAs<PointerType>(); Qualifiers Quals = MakeQualifiers(PT->getPointeeType()); Quals.removeObjCGCAttr(); Base = LValue::MakeAddr(Ptr, Quals); + } else if (E->getBase()->isLvalue(getContext()) == Expr::LV_Valid) { + // Otherwise, if the base is an lvalue ( as in the case of foo.x.x), + // emit the base as an lvalue. + assert(E->getBase()->getType()->isVectorType()); + Base = EmitLValue(E->getBase()); + } else { + // Otherwise, the base is a normal rvalue (as in (V+V).x), emit it as such. + const VectorType *VT = E->getBase()->getType()->getAs<VectorType>(); + assert(VT && "Result must be a vector"); + llvm::Value *Vec = EmitScalarExpr(E->getBase()); + + // Store the vector to memory (because LValue wants an address). + llvm::Value *VecMem =CreateTempAlloca(ConvertType(E->getBase()->getType())); + Builder.CreateStore(Vec, VecMem); + Base = LValue::MakeAddr(VecMem, Qualifiers()); } - + // Encode the element access list into a vector of unsigned indices. llvm::SmallVector<unsigned, 4> Indices; E->getEncodedElementAccess(Indices); @@ -1181,7 +1235,6 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { llvm::Constant *BaseElts = Base.getExtVectorElts(); llvm::SmallVector<llvm::Constant *, 4> CElts; - const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext); for (unsigned i = 0, e = Indices.size(); i != e; ++i) { if (isa<llvm::ConstantAggregateZero>(BaseElts)) CElts.push_back(llvm::ConstantInt::get(Int32Ty, 0)); @@ -1325,12 +1378,20 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){ LValue CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) { if (E->isLvalue(getContext()) == Expr::LV_Valid) { + if (int Cond = ConstantFoldsToSimpleInteger(E->getCond())) { + Expr *Live = Cond == 1 ? E->getLHS() : E->getRHS(); + if (Live) + return EmitLValue(Live); + } + + if (!E->getLHS()) + return EmitUnsupportedLValue(E, "conditional operator with missing LHS"); + llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true"); llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false"); llvm::BasicBlock *ContBlock = createBasicBlock("cond.end"); - llvm::Value *Cond = EvaluateExprAsBool(E->getCond()); - Builder.CreateCondBr(Cond, LHSBlock, RHSBlock); + EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock); EmitBlock(LHSBlock); @@ -1390,6 +1451,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CastExpr::CK_NoOp: case CastExpr::CK_ConstructorConversion: case CastExpr::CK_UserDefinedConversion: + case CastExpr::CK_AnyPointerToObjCPointerCast: return EmitLValue(E->getSubExpr()); case CastExpr::CK_DerivedToBase: { @@ -1464,13 +1526,14 @@ LValue CodeGenFunction::EmitNullInitializationLValue( //===--------------------------------------------------------------------===// -RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) { +RValue CodeGenFunction::EmitCallExpr(const CallExpr *E, + ReturnValueSlot ReturnValue) { // Builtins never have block type. if (E->getCallee()->getType()->isBlockPointerType()) - return EmitBlockCallExpr(E); + return EmitBlockCallExpr(E, ReturnValue); if (const CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(E)) - return EmitCXXMemberCallExpr(CE); + return EmitCXXMemberCallExpr(CE, ReturnValue); const Decl *TargetDecl = 0; if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E->getCallee())) { @@ -1484,7 +1547,7 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) { if (const CXXOperatorCallExpr *CE = dyn_cast<CXXOperatorCallExpr>(E)) if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(TargetDecl)) - return EmitCXXOperatorMemberCallExpr(CE, MD); + return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue); if (isa<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) { // C++ [expr.pseudo]p1: @@ -1497,7 +1560,7 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) { } llvm::Value *Callee = EmitScalarExpr(E->getCallee()); - return EmitCall(Callee, E->getCallee()->getType(), + return EmitCall(E->getCallee()->getType(), Callee, ReturnValue, E->arg_begin(), E->arg_end(), TargetDecl); } @@ -1658,7 +1721,8 @@ LValue CodeGenFunction::EmitPointerToDataMemberLValue(const FieldDecl *Field) { return LValue::MakeAddr(V, MakeQualifiers(Field->getType())); } -RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType, +RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, + ReturnValueSlot ReturnValue, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, const Decl *TargetDecl) { @@ -1683,7 +1747,7 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType, CallingConvention = F->getCallingConv(); return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args, CallingConvention), - Callee, Args, TargetDecl); + Callee, ReturnValue, Args, TargetDecl); } LValue CodeGenFunction:: diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 2c122eb..b95fd79 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -106,6 +106,7 @@ public: void VisitConditionalOperator(const ConditionalOperator *CO); void VisitChooseExpr(const ChooseExpr *CE); void VisitInitListExpr(InitListExpr *E); + void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { Visit(DAE->getExpr()); } @@ -271,6 +272,13 @@ void AggExprEmitter::VisitCallExpr(const CallExpr *E) { return; } + // If the struct doesn't require GC, we can just pass the destination + // directly to EmitCall. + if (!RequiresGCollection) { + CGF.EmitCallExpr(E, ReturnValueSlot(DestPtr, VolatileDest)); + return; + } + RValue RV = CGF.EmitCallExpr(E); EmitFinalDestCopy(E, RV); } @@ -388,12 +396,16 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { } void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) { + if (!E->getLHS()) { + CGF.ErrorUnsupported(E, "conditional operator with missing LHS"); + return; + } + llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true"); llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false"); llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end"); - llvm::Value *Cond = CGF.EvaluateExprAsBool(E->getCond()); - Builder.CreateCondBr(Cond, LHSBlock, RHSBlock); + CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock); CGF.StartConditionalBranch(); CGF.EmitBlock(LHSBlock); @@ -457,16 +469,45 @@ AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) { Val = CGF.CreateTempAlloca(CGF.ConvertTypeForMem(E->getType()), "tmp"); } + if (E->requiresZeroInitialization()) + EmitNullInitializationToLValue(LValue::MakeAddr(Val, + // FIXME: Qualifiers()? + E->getType().getQualifiers()), + E->getType()); + CGF.EmitCXXConstructExpr(Val, E); } void AggExprEmitter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { - CGF.EmitCXXExprWithTemporaries(E, DestPtr, VolatileDest, IsInitializer); + llvm::Value *Val = DestPtr; + + if (!Val) { + // Create a temporary variable. + Val = CGF.CreateTempAlloca(CGF.ConvertTypeForMem(E->getType()), "tmp"); + } + CGF.EmitCXXExprWithTemporaries(E, Val, VolatileDest, IsInitializer); } void AggExprEmitter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { - LValue lvalue = LValue::MakeAddr(DestPtr, Qualifiers()); - EmitNullInitializationToLValue(lvalue, E->getType()); + llvm::Value *Val = DestPtr; + + if (!Val) { + // Create a temporary variable. + Val = CGF.CreateTempAlloca(CGF.ConvertTypeForMem(E->getType()), "tmp"); + } + LValue LV = LValue::MakeAddr(Val, Qualifiers()); + EmitNullInitializationToLValue(LV, E->getType()); +} + +void AggExprEmitter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { + llvm::Value *Val = DestPtr; + + if (!Val) { + // Create a temporary variable. + Val = CGF.CreateTempAlloca(CGF.ConvertTypeForMem(E->getType()), "tmp"); + } + LValue LV = LValue::MakeAddr(Val, Qualifiers()); + EmitNullInitializationToLValue(LV, E->getType()); } void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) { diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 150f11e..7992322 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -78,7 +78,6 @@ static uint64_t CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) { } return CalculateCookiePadding(Ctx, E->getAllocatedType()); - QualType T = E->getAllocatedType(); } static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, @@ -212,7 +211,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // Emit the call to new. RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs), - CGM.GetAddrOfFunction(NewFD), NewArgs, NewFD); + CGM.GetAddrOfFunction(NewFD), ReturnValueSlot(), NewArgs, NewFD); // If an allocation function is declared with an empty exception specification // it returns null to indicate failure to allocate storage. [expr.new]p13. @@ -354,7 +353,7 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, // Emit the call to delete. EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(), DeleteArgs), - CGM.GetAddrOfFunction(DeleteFD), + CGM.GetAddrOfFunction(DeleteFD), ReturnValueSlot(), DeleteArgs, DeleteFD); } @@ -406,7 +405,7 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { /*isVariadic=*/false); llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty); - EmitCXXMemberCall(Dtor, Callee, Ptr, 0, 0); + EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, 0, 0); // The dtor took care of deleting the object. ShouldCallDelete = false; @@ -426,9 +425,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 +470,23 @@ llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL); V = Builder.CreateLoad(V); return V; - } - return Builder.CreateBitCast(CGM.GenerateRTTI(RD), LTy); + } } - return Builder.CreateBitCast(CGM.GenerateRTTI(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<NonNullAttr>(), we don't set this CanBeZero = true; if (InnerType->isVoidType()) @@ -495,14 +496,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<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl()); + if (SrcTy->isPointerType() || SrcTy->isReferenceType()) + SrcTy = SrcTy->getPointeeType(); + SrcTy = SrcTy.getUnqualifiedType(); + + if (DestTy->isPointerType() || DestTy->isReferenceType()) + DestTy = DestTy->getPointeeType(); + DestTy = DestTy.getUnqualifiedType(); llvm::BasicBlock *ContBlock = createBasicBlock(); llvm::BasicBlock *NullBlock = 0; @@ -510,15 +510,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 +540,27 @@ 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<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl()); // FIXME: Calculate better hint. llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL); - llvm::Value *SrcArg = CGM.GenerateRTTIRef(SrcTy); - llvm::Value *DstArg = CGM.GenerateRTTIRef(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.getUnqualifiedType()); + llvm::Value *DestArg + = CGM.GetAddrOfRTTIDescriptor(DestTy.getUnqualifiedType()); + 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/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index 7fa8ffb..be2239f 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -626,6 +626,14 @@ ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) { ComplexPairTy ComplexExprEmitter:: VisitConditionalOperator(const ConditionalOperator *E) { + if (!E->getLHS()) { + CGF.ErrorUnsupported(E, "conditional operator with missing LHS"); + const llvm::Type *EltTy = + CGF.ConvertType(E->getType()->getAs<ComplexType>()->getElementType()); + llvm::Value *U = llvm::UndefValue::get(EltTy); + return ComplexPairTy(U, U); + } + TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); TestAndClearIgnoreRealAssign(); @@ -634,8 +642,7 @@ VisitConditionalOperator(const ConditionalOperator *E) { llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false"); llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end"); - llvm::Value *Cond = CGF.EvaluateExprAsBool(E->getCond()); - Builder.CreateCondBr(Cond, LHSBlock, RHSBlock); + CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock); CGF.EmitBlock(LHSBlock); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 2f31c05..93646d6 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -69,6 +69,7 @@ public: const llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); } LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); } + LValue EmitCheckedLValue(const Expr *E) { return CGF.EmitCheckedLValue(E); } Value *EmitLoadOfLValue(LValue LV, QualType T) { return CGF.EmitLoadOfLValue(LV, T).getScalarVal(); @@ -78,7 +79,7 @@ public: /// value l-value, this method emits the address of the l-value, then loads /// and returns the result. Value *EmitLoadOfLValue(const Expr *E) { - return EmitLoadOfLValue(EmitLValue(E), E->getType()); + return EmitLoadOfLValue(EmitCheckedLValue(E), E->getType()); } /// EmitConversionToBool - Convert the specified expression value to a @@ -327,16 +328,16 @@ public: Value *VisitBin ## OP ## Assign(const CompoundAssignOperator *E) { \ return EmitCompoundAssign(E, &ScalarExprEmitter::Emit ## OP); \ } - HANDLEBINOP(Mul); - HANDLEBINOP(Div); - HANDLEBINOP(Rem); - HANDLEBINOP(Add); - HANDLEBINOP(Sub); - HANDLEBINOP(Shl); - HANDLEBINOP(Shr); - HANDLEBINOP(And); - HANDLEBINOP(Xor); - HANDLEBINOP(Or); + HANDLEBINOP(Mul) + HANDLEBINOP(Div) + HANDLEBINOP(Rem) + HANDLEBINOP(Add) + HANDLEBINOP(Sub) + HANDLEBINOP(Shl) + HANDLEBINOP(Shr) + HANDLEBINOP(And) + HANDLEBINOP(Xor) + HANDLEBINOP(Or) #undef HANDLEBINOP // Comparisons. @@ -346,12 +347,12 @@ public: Value *VisitBin##CODE(const BinaryOperator *E) { \ return EmitCompare(E, llvm::ICmpInst::UI, llvm::ICmpInst::SI, \ llvm::FCmpInst::FP); } - VISITCOMP(LT, ICMP_ULT, ICMP_SLT, FCMP_OLT); - VISITCOMP(GT, ICMP_UGT, ICMP_SGT, FCMP_OGT); - VISITCOMP(LE, ICMP_ULE, ICMP_SLE, FCMP_OLE); - VISITCOMP(GE, ICMP_UGE, ICMP_SGE, FCMP_OGE); - VISITCOMP(EQ, ICMP_EQ , ICMP_EQ , FCMP_OEQ); - VISITCOMP(NE, ICMP_NE , ICMP_NE , FCMP_UNE); + VISITCOMP(LT, ICMP_ULT, ICMP_SLT, FCMP_OLT) + VISITCOMP(GT, ICMP_UGT, ICMP_SGT, FCMP_OGT) + VISITCOMP(LE, ICMP_ULE, ICMP_SLE, FCMP_OLE) + VISITCOMP(GE, ICMP_UGE, ICMP_SGE, FCMP_OGE) + VISITCOMP(EQ, ICMP_EQ , ICMP_EQ , FCMP_OEQ) + VISITCOMP(NE, ICMP_NE , ICMP_NE , FCMP_UNE) #undef VISITCOMP Value *VisitBinAssign (const BinaryOperator *E); @@ -815,6 +816,7 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { return Builder.CreateBitCast(Src, ConvertType(DestTy)); } case CastExpr::CK_NoOp: + case CastExpr::CK_UserDefinedConversion: return Visit(const_cast<Expr*>(E)); case CastExpr::CK_BaseToDerived: { @@ -902,7 +904,6 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { return Src; } - case CastExpr::CK_UserDefinedConversion: case CastExpr::CK_ConstructorConversion: assert(0 && "Should be unreachable!"); break; @@ -1198,7 +1199,7 @@ BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) { Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) { bool Ignore = TestAndClearIgnoreResultAssign(); - QualType LHSTy = E->getLHS()->getType(), RHSTy = E->getRHS()->getType(); + QualType LHSTy = E->getLHS()->getType(); BinOpInfo OpInfo; @@ -1217,7 +1218,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, OpInfo.Ty = E->getComputationResultType(); OpInfo.E = E; // Load/convert the LHS. - LValue LHSLV = EmitLValue(E->getLHS()); + LValue LHSLV = EmitCheckedLValue(E->getLHS()); OpInfo.LHS = EmitLoadOfLValue(LHSLV, LHSTy); OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy, E->getComputationLHSType()); @@ -1654,7 +1655,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { // __block variables need to have the rhs evaluated first, plus this should // improve codegen just a little. Value *RHS = Visit(E->getRHS()); - LValue LHS = EmitLValue(E->getLHS()); + LValue LHS = EmitCheckedLValue(E->getLHS()); // Store the value into the LHS. Bit-fields are handled specially // because the result is altered by the store, i.e., [C99 6.5.16p1] diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 2fe3f5b..ac391d9 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -190,7 +190,7 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, // FIXME: We shouldn't need to get the function info here, the // runtime already should have computed it to build the function. RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args), - GetPropertyFn, Args); + GetPropertyFn, ReturnValueSlot(), Args); // We need to fix the type here. Ivars with copy & retain are // always objects so we don't need to worry about complex or // aggregates. @@ -277,8 +277,8 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, getContext().BoolTy)); // FIXME: We shouldn't need to get the function info here, the runtime // already should have computed it to build the function. - EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args), - SetPropertyFn, Args); + EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args), SetPropertyFn, + ReturnValueSlot(), Args); } else { // FIXME: Find a clean way to avoid AST node creation. SourceLocation Loc = PD->getLocation(); @@ -553,7 +553,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ // FIXME: We shouldn't need to get the function info here, the runtime already // should have computed it to build the function. EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2), - EnumerationMutationFn, Args2); + EnumerationMutationFn, ReturnValueSlot(), Args2); EmitBlock(WasNotMutated); diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index be772c7..95f67ae 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -450,7 +450,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, llvm::Value *imp = CGF.Builder.CreateCall(lookupFunction, lookupArgs, lookupArgs+2); - return CGF.EmitCall(FnInfo, imp, ActualArgs); + return CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs); } /// Generate code for a message send expression. @@ -536,7 +536,7 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, imp = Builder.CreateCall2(lookupFunction, Receiver, cmd); } - return CGF.EmitCall(FnInfo, imp, ActualArgs); + return CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs); } /// Generates a MethodList. Used in construction of a objc_class and @@ -1607,7 +1607,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, Params.push_back(PtrTy); llvm::Value *RethrowFn = CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), - Params, false), "_Unwind_Resume_or_Rethrow"); + Params, false), "objc_exception_throw"); bool isTry = isa<ObjCAtTryStmt>(S); llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); @@ -1618,7 +1618,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); - // GNU runtime does not currently support @synchronized() + // @synchronized() if (!isTry) { std::vector<const llvm::Type*> Args(1, IdTy); llvm::FunctionType *FTy = @@ -1770,7 +1770,13 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, ESelArgs.clear(); ESelArgs.push_back(Exc); ESelArgs.push_back(Personality); - ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); + // If there is a @catch or @finally clause in outside of this one then we + // need to make sure that we catch and rethrow it. + if (PrevLandingPad) { + ESelArgs.push_back(NULLPtr); + } else { + ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); + } CGF.Builder.CreateCall(llvm_eh_selector, ESelArgs.begin(), ESelArgs.end(), "selector"); CGF.Builder.CreateCall(llvm_eh_typeid_for, @@ -1811,11 +1817,23 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.EmitBranch(FinallyEnd); CGF.EmitBlock(FinallyRethrow); - CGF.Builder.CreateCall(RethrowFn, CGF.Builder.CreateLoad(RethrowPtr)); - CGF.Builder.CreateUnreachable(); - CGF.EmitBlock(FinallyEnd); + llvm::Value *ExceptionObject = CGF.Builder.CreateLoad(RethrowPtr); + llvm::BasicBlock *UnwindBB = CGF.getInvokeDest(); + if (!UnwindBB) { + CGF.Builder.CreateCall(RethrowFn, ExceptionObject); + // Exception always thrown, next instruction is never reached. + CGF.Builder.CreateUnreachable(); + } else { + // If there is a @catch block outside this scope, we invoke instead of + // calling because we may return to this function. This is very slow, but + // some people still do it. It would be nice to add an optimised path for + // this. + CGF.Builder.CreateInvoke(RethrowFn, UnwindBB, UnwindBB, &ExceptionObject, + &ExceptionObject+1); + } + CGF.EmitBlock(FinallyEnd); } void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index fb920f0..727746f 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1581,7 +1581,7 @@ CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, assert(Fn && "EmitLegacyMessageSend - unknown API"); Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy)); - return CGF.EmitCall(FnInfo, Fn, ActualArgs); + return CGF.EmitCall(FnInfo, Fn, ReturnValueSlot(), ActualArgs); } llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder, @@ -3351,7 +3351,6 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( SkipScanIvars.push_back(SkScan); } - bool BytesSkipped = false; if (!SkipIvars.empty()) { unsigned int LastIndex = SkipIvars.size()-1; int LastByteSkipped = @@ -3360,9 +3359,8 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( int LastByteScanned = IvarsInfo[LastIndex].ivar_bytepos + IvarsInfo[LastIndex].ivar_size * WordSize; - BytesSkipped = (LastByteSkipped > LastByteScanned); // Compute number of bytes to skip at the tail end of the last ivar scanned. - if (BytesSkipped) { + if (LastByteSkipped > LastByteScanned) { unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize; SKIP_SCAN SkScan; SkScan.skip = TotalWords - (LastByteScanned/WordSize); @@ -3393,8 +3391,6 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( unsigned int skip_big = SkipScanIvars[i].skip / 0xf; unsigned int scan_big = SkipScanIvars[i].scan / 0xf; - if (skip_small > 0 || skip_big > 0) - BytesSkipped = true; // first skip big. for (unsigned int ix = 0; ix < skip_big; ix++) BitMap += (unsigned char)(0xf0); @@ -5169,7 +5165,7 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true); Callee = CGF.Builder.CreateBitCast(Callee, llvm::PointerType::getUnqual(FTy)); - return CGF.EmitCall(FnInfo1, Callee, ActualArgs); + return CGF.EmitCall(FnInfo1, Callee, ReturnValueSlot(), ActualArgs); } /// Generate code for a message send expression in the nonfragile abi. diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp index 02de00e..db6c507 100644 --- a/lib/CodeGen/CGRTTI.cpp +++ b/lib/CodeGen/CGRTTI.cpp @@ -21,76 +21,48 @@ namespace { class RTTIBuilder { CodeGenModule &CGM; // Per-module state. llvm::LLVMContext &VMContext; + const llvm::Type *Int8PtrTy; - llvm::SmallSet<const CXXRecordDecl *, 16> SeenVBase; - llvm::SmallSet<const CXXRecordDecl *, 32> SeenBase; - - // Type info flags. - enum { - /// TI_Const - Type has const qualifier. - TI_Const = 0x1, - - /// TI_Volatile - Type has volatile qualifier. - TI_Volatile = 0x2, - - /// TI_Restrict - Type has restrict qualifier. - TI_Restrict = 0x4, - - /// TI_Incomplete - Type is incomplete. - TI_Incomplete = 0x8, + + /// Fields - The fields of the RTTI descriptor currently being built. + llvm::SmallVector<llvm::Constant *, 16> Fields; - /// TI_ContainingClassIncomplete - Containing class is incomplete. - /// (in pointer to member). - TI_ContainingClassIncomplete = 0x10 - }; + /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI + /// descriptor of the given type. + llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty); + + /// BuildVtablePointer - Build the vtable pointer for the given type. + void BuildVtablePointer(const Type *Ty); + + /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single + /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b. + void BuildSIClassTypeInfo(const CXXRecordDecl *RD); + + /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for + /// classes with bases that do not satisfy the abi::__si_class_type_info + /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c. + void BuildVMIClassTypeInfo(const CXXRecordDecl *RD); + + /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used + /// for pointer types. + void BuildPointerTypeInfo(const PointerType *Ty); + + /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info + /// struct, used for member pointer types. + void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty); public: RTTIBuilder(CodeGenModule &cgm) : CGM(cgm), VMContext(cgm.getModule().getContext()), Int8PtrTy(llvm::Type::getInt8PtrTy(VMContext)) { } - /// BuildVtableRef - Build a reference to a vtable. - llvm::Constant *BuildVtableRef(const char *Name) { - // Build a descriptor for Name - llvm::Constant *GV = CGM.getModule().getGlobalVariable(Name); - if (GV) - GV = llvm::ConstantExpr::getBitCast(GV, - llvm::PointerType::get(Int8PtrTy, 0)); - else { - llvm::GlobalVariable::LinkageTypes linktype; - linktype = llvm::GlobalValue::ExternalLinkage; - GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, - true, linktype, 0, Name); - } - llvm::Constant *C; - C = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 2); - C = llvm::ConstantExpr::getInBoundsGetElementPtr(GV, &C, 1); - return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); - } - - // FIXME: This should be removed, and clients should pass in the linkage - // directly instead. - static inline llvm::GlobalVariable::LinkageTypes - GetLinkageFromExternFlag(bool Extern) { - if (Extern) - return llvm::GlobalValue::WeakODRLinkage; - - return llvm::GlobalValue::InternalLinkage; - } - - // FIXME: This should be removed, and clients should pass in the linkage - // directly instead. - llvm::Constant *BuildName(QualType Ty, bool Hidden, bool Extern) { - return BuildName(Ty, Hidden, GetLinkageFromExternFlag(Extern)); - } - llvm::Constant *BuildName(QualType Ty, bool Hidden, llvm::GlobalVariable::LinkageTypes Linkage) { llvm::SmallString<256> OutName; CGM.getMangleContext().mangleCXXRTTIName(Ty, OutName); llvm::StringRef Name = OutName.str(); - llvm::GlobalVariable *OGV = CGM.getModule().getGlobalVariable(Name); + llvm::GlobalVariable *OGV = CGM.getModule().getNamedGlobal(Name); if (OGV && !OGV->isDeclaration()) return llvm::ConstantExpr::getBitCast(OGV, Int8PtrTy); @@ -109,397 +81,789 @@ public: if (Hidden) GV->setVisibility(llvm::GlobalVariable::HiddenVisibility); return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); - }; - - /// - BuildFlags - Build a psABI __flags value for __vmi_class_type_info. - llvm::Constant *BuildFlags(int f) { - return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f); } - /// BuildBaseCount - Build a psABI __base_count value for - /// __vmi_class_type_info. - llvm::Constant *BuildBaseCount(unsigned c) { - return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), c); + // FIXME: unify with DecideExtern + bool DecideHidden(QualType Ty) { + // For this type, see if all components are never hidden. + if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) + return (DecideHidden(MPT->getPointeeType()) + && DecideHidden(QualType(MPT->getClass(), 0))); + if (const PointerType *PT = Ty->getAs<PointerType>()) + return DecideHidden(PT->getPointeeType()); + if (const FunctionType *FT = Ty->getAs<FunctionType>()) { + if (DecideHidden(FT->getResultType()) == false) + return false; + if (const FunctionProtoType *FPT = Ty->getAs<FunctionProtoType>()) { + for (unsigned i = 0; i <FPT->getNumArgs(); ++i) + if (DecideHidden(FPT->getArgType(i)) == false) + return false; + for (unsigned i = 0; i <FPT->getNumExceptions(); ++i) + if (DecideHidden(FPT->getExceptionType(i)) == false) + return false; + return true; + } + } + if (const RecordType *RT = Ty->getAs<RecordType>()) + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) + return CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden; + return false; } + + // Pointer type info flags. + enum { + /// PTI_Const - Type has const qualifier. + PTI_Const = 0x1, + + /// PTI_Volatile - Type has volatile qualifier. + PTI_Volatile = 0x2, + + /// PTI_Restrict - Type has restrict qualifier. + PTI_Restrict = 0x4, + + /// PTI_Incomplete - Type is incomplete. + PTI_Incomplete = 0x8, + + /// PTI_ContainingClassIncomplete - Containing class is incomplete. + /// (in pointer to member). + PTI_ContainingClassIncomplete = 0x10 + }; + + // VMI type info flags. + enum { + /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance. + VMI_NonDiamondRepeat = 0x1, + + /// VMI_DiamondShaped - Class is diamond shaped. + VMI_DiamondShaped = 0x2 + }; + + // Base class type info flags. + enum { + /// BCTI_Virtual - Base class is virtual. + BCTI_Virtual = 0x1, + + /// BCTI_Public - Base class is public. + BCTI_Public = 0x2 + }; + + /// BuildTypeInfo - Build the RTTI type info struct for the given type. + llvm::Constant *BuildTypeInfo(QualType Ty); +}; +} - 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;; +llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) { + // Mangle the RTTI name. + llvm::SmallString<256> OutName; + CGM.getMangleContext().mangleCXXRTTI(Ty, OutName); + llvm::StringRef Name = OutName.str(); - C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype, - 0, Name); - return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); + // Look for an existing global. + llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name); + + if (!GV) { + // Create a new global variable. + GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, /*Constant=*/true, + llvm::GlobalValue::ExternalLinkage, 0, Name); } + + return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); +} - llvm::Constant *Buildclass_type_infoRef(const CXXRecordDecl *RD) { - return BuildTypeRef(CGM.getContext().getTagDeclType(RD)); - } +/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type +/// info for that type is defined in the standard library. +static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { + // Itanium C++ ABI 2.9.2: + // Basic type information (e.g. for "int", "bool", etc.) will be kept in + // the run-time support library. Specifically, the run-time support + // library should contain type_info objects for the types X, X* and + // X const*, for every X in: void, bool, wchar_t, char, unsigned char, + // signed char, short, unsigned short, int, unsigned int, long, + // unsigned long, long long, unsigned long long, float, double, long double, + // char16_t, char32_t, and the IEEE 754r decimal and half-precision + // floating point types. + switch (Ty->getKind()) { + case BuiltinType::Void: + case BuiltinType::Bool: + case BuiltinType::WChar: + case BuiltinType::Char_U: + case BuiltinType::Char_S: + case BuiltinType::UChar: + case BuiltinType::SChar: + case BuiltinType::Short: + case BuiltinType::UShort: + case BuiltinType::Int: + case BuiltinType::UInt: + case BuiltinType::Long: + case BuiltinType::ULong: + case BuiltinType::LongLong: + case BuiltinType::ULongLong: + case BuiltinType::Float: + case BuiltinType::Double: + case BuiltinType::LongDouble: + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::Int128: + case BuiltinType::UInt128: + return true; + + case BuiltinType::Overload: + case BuiltinType::Dependent: + case BuiltinType::UndeducedAuto: + assert(false && "Should not see this type here!"); + + case BuiltinType::NullPtr: + assert(false && "FIXME: nullptr_t is not handled!"); - /// CalculateFlags - Calculate the flags for the __vmi_class_type_info - /// datastructure. 1 for non-diamond repeated inheritance, 2 for a dimond - /// shaped class. - int CalculateFlags(const CXXRecordDecl*RD) { - int flags = 0; - if (SeenBase.count(RD)) - flags |= 1; - else - SeenBase.insert(RD); - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - if (i->isVirtual()) { - if (SeenVBase.count(Base)) - flags |= 2; - else - SeenVBase.insert(Base); - } - flags |= CalculateFlags(Base); - } - return flags; + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + assert(false && "FIXME: Objective-C types are unsupported!"); } + + // Silent gcc. + return false; +} - bool SimpleInheritance(const CXXRecordDecl *RD) { - if (RD->getNumBases() != 1) - return false; - CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(); - if (i->isVirtual()) - return false; - if (i->getAccessSpecifier() != AS_public) - return false; +static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) { + QualType PointeeTy = PointerTy->getPointeeType(); + const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy); + if (!BuiltinTy) + return false; + + // Check the qualifiers. + Qualifiers Quals = PointeeTy.getQualifiers(); + Quals.removeConst(); + + if (!Quals.empty()) + return false; + + return TypeInfoIsInStandardLibrary(BuiltinTy); +} - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - if (Layout.getBaseClassOffset(Base) != 0) +/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for +/// the given type exists somewhere else, and that we should not emit the typ +/// information in this translation unit. +bool ShouldUseExternalRTTIDescriptor(QualType Ty) { + // Type info for builtin types is defined in the standard library. + if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty)) + return TypeInfoIsInStandardLibrary(BuiltinTy); + + // Type info for some pointer types to builtin types is defined in the + // standard library. + if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty)) + return TypeInfoIsInStandardLibrary(PointerTy); + + if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); + if (!RD->isDynamicClass()) return false; - return true; - } - llvm::Constant *finish(llvm::Constant *const *Values, unsigned NumValues, - llvm::GlobalVariable *GV, - llvm::StringRef Name, bool Hidden, - llvm::GlobalVariable::LinkageTypes Linkage) { - llvm::Constant *C = - llvm::ConstantStruct::get(VMContext, Values, NumValues, /*Packed=*/false); - - llvm::GlobalVariable *OGV = GV; - GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, Linkage, - C, Name); - if (OGV) { - GV->takeName(OGV); - llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, - OGV->getType()); - OGV->replaceAllUsesWith(NewPtr); - OGV->eraseFromParent(); + // Get the key function. + const CXXMethodDecl *KeyFunction = RD->getASTContext().getKeyFunction(RD); + if (KeyFunction && !KeyFunction->getBody()) { + // The class has a key function, but it is not defined in this translation + // unit, so we should use the external descriptor for it. + return true; } - if (Hidden) - GV->setVisibility(llvm::GlobalVariable::HiddenVisibility); - return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); } + + return false; +} +/// IsIncompleteClassType - Returns whether the given record type is incomplete. +static bool IsIncompleteClassType(const RecordType *RecordTy) { + return !RecordTy->getDecl()->isDefinition(); +} + +/// ContainsIncompleteClassType - Returns whether the given type contains an +/// incomplete class type. This is true if +/// +/// * The given type is an incomplete class type. +/// * The given type is a pointer type whose pointee type contains an +/// incomplete class type. +/// * The given type is a member pointer type whose class is an incomplete +/// class type. +/// * The given type is a member pointer type whoise pointee type contains an +/// incomplete class type. +/// is an indirect or direct pointer to an incomplete class type. +static bool ContainsIncompleteClassType(QualType Ty) { + if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { + if (IsIncompleteClassType(RecordTy)) + return true; + } + + if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty)) + return ContainsIncompleteClassType(PointerTy->getPointeeType()); + + if (const MemberPointerType *MemberPointerTy = + dyn_cast<MemberPointerType>(Ty)) { + // Check if the class type is incomplete. + const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass()); + if (IsIncompleteClassType(ClassType)) + return true; + + return ContainsIncompleteClassType(MemberPointerTy->getPointeeType()); + } + + return false; +} - llvm::Constant * - Buildclass_type_info(const CXXRecordDecl *RD, - llvm::GlobalVariable::LinkageTypes Linkage) { - std::vector<llvm::Constant *> info; - assert(info.empty() && "Info vector must be empty!"); +/// getTypeInfoLinkage - Return the linkage that the type info and type info +/// name constants should have for the given type. +static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(QualType Ty) { + // Itanium C++ ABI 2.9.5p7: + // In addition, it and all of the intermediate abi::__pointer_type_info + // structs in the chain down to the abi::__class_type_info for the + // incomplete class type must be prevented from resolving to the + // corresponding type_info structs for the complete class type, possibly + // by making them local static objects. Finally, a dummy class RTTI is + // generated for the incomplete type that will not resolve to the final + // complete class RTTI (because the latter need not exist), possibly by + // making it a local static object. + if (ContainsIncompleteClassType(Ty)) + return llvm::GlobalValue::InternalLinkage; + + switch (Ty->getTypeClass()) { + default: + // FIXME: We need to add code to handle all types. + assert(false && "Unhandled type!"); + break; + + case Type::Pointer: { + const PointerType *PointerTy = cast<PointerType>(Ty); + + // If the pointee type has internal linkage, then the pointer type needs to + // have it as well. + if (getTypeInfoLinkage(PointerTy->getPointeeType()) == + llvm::GlobalVariable::InternalLinkage) + return llvm::GlobalVariable::InternalLinkage; - llvm::Constant *C; + return llvm::GlobalVariable::WeakODRLinkage; + } - llvm::SmallString<256> OutName; - CGM.getMangleContext().mangleCXXRTTI(CGM.getContext().getTagDeclType(RD), - OutName); - llvm::StringRef Name = OutName.str(); + case Type::Enum: { + const EnumType *EnumTy = cast<EnumType>(Ty); + const EnumDecl *ED = EnumTy->getDecl(); + + // If we're in an anonymous namespace, then we always want internal linkage. + if (ED->isInAnonymousNamespace() || !ED->hasLinkage()) + return llvm::GlobalVariable::InternalLinkage; + + return llvm::GlobalValue::WeakODRLinkage; + } - llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Name); - if (GV && !GV->isDeclaration()) - return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); + case Type::Record: { + const RecordType *RecordTy = cast<RecordType>(Ty); + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); // If we're in an anonymous namespace, then we always want internal linkage. if (RD->isInAnonymousNamespace() || !RD->hasLinkage()) - Linkage = llvm::GlobalVariable::InternalLinkage; + return llvm::GlobalVariable::InternalLinkage; - bool Hidden = CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden; - - bool simple = false; - if (RD->getNumBases() == 0) - C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE"); - else if (SimpleInheritance(RD)) { - simple = true; - C = BuildVtableRef("_ZTVN10__cxxabiv120__si_class_type_infoE"); - } else - C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE"); - info.push_back(C); - info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden, - Linkage)); - - // If we have no bases, there are no more fields. - if (RD->getNumBases()) { - if (!simple) { - info.push_back(BuildFlags(CalculateFlags(RD))); - info.push_back(BuildBaseCount(RD->getNumBases())); - } - - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - info.push_back(CGM.GetAddrOfRTTI(Base)); - if (simple) - break; - int64_t offset; - if (!i->isVirtual()) - offset = Layout.getBaseClassOffset(Base)/8; - else - offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base); - offset <<= 8; - // Now set the flags. - offset += i->isVirtual() ? 1 : 0;; - offset += i->getAccessSpecifier() == AS_public ? 2 : 0; - const llvm::Type *LongTy = - CGM.getTypes().ConvertType(CGM.getContext().LongTy); - C = llvm::ConstantInt::get(LongTy, offset); - info.push_back(C); - } + if (!RD->isDynamicClass()) + return llvm::GlobalValue::WeakODRLinkage; + + // Get the key function. + const CXXMethodDecl *KeyFunction = RD->getASTContext().getKeyFunction(RD); + if (!KeyFunction) { + // There is no key function, the RTTI descriptor is emitted with weak_odr + // linkage. + return llvm::GlobalValue::WeakODRLinkage; } - return finish(&info[0], info.size(), GV, Name, Hidden, Linkage); - } + // If the key function is defined, but inlined, then the RTTI descriptor is + // emitted with weak_odr linkage. + const FunctionDecl* KeyFunctionDefinition; + KeyFunction->getBody(KeyFunctionDefinition); - /// - BuildFlags - Build a __flags value for __pbase_type_info. - llvm::Constant *BuildInt(unsigned n) { - return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), n); + if (KeyFunctionDefinition->isInlined()) + return llvm::GlobalValue::WeakODRLinkage; + + // Otherwise, the RTTI descriptor is emitted with external linkage. + return llvm::GlobalValue::ExternalLinkage; } - bool DecideExtern(QualType Ty) { - // For this type, see if all components are never in an anonymous namespace. - if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) - return (DecideExtern(MPT->getPointeeType()) - && DecideExtern(QualType(MPT->getClass(), 0))); - if (const PointerType *PT = Ty->getAs<PointerType>()) - return DecideExtern(PT->getPointeeType()); - if (const RecordType *RT = Ty->getAs<RecordType>()) - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) - return !RD->isInAnonymousNamespace() && RD->hasLinkage(); - return true; - } + case Type::Vector: + case Type::ExtVector: + case Type::Builtin: + return llvm::GlobalValue::WeakODRLinkage; - bool DecideHidden(QualType Ty) { - // For this type, see if all components are never hidden. - if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) - return (DecideHidden(MPT->getPointeeType()) - && DecideHidden(QualType(MPT->getClass(), 0))); - if (const PointerType *PT = Ty->getAs<PointerType>()) - return DecideHidden(PT->getPointeeType()); - if (const RecordType *RT = Ty->getAs<RecordType>()) - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) - return CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden; - return false; - } + case Type::FunctionProto: { + const FunctionProtoType *FPT = cast<FunctionProtoType>(Ty); - llvm::Constant *BuildPointerType(QualType Ty) { - std::vector<llvm::Constant *> info; - assert(info.empty() && "Info vector must be empty!"); + // Check the return type. + if (getTypeInfoLinkage(FPT->getResultType()) == + llvm::GlobalValue::InternalLinkage) + return llvm::GlobalValue::InternalLinkage; + + // Check the parameter types. + for (unsigned i = 0; i != FPT->getNumArgs(); ++i) { + if (getTypeInfoLinkage(FPT->getArgType(i)) == + llvm::GlobalValue::InternalLinkage) + return llvm::GlobalValue::InternalLinkage; + } - llvm::Constant *C; + return llvm::GlobalValue::WeakODRLinkage; + } + + case Type::ConstantArray: + case Type::IncompleteArray: { + const ArrayType *AT = cast<ArrayType>(Ty); + + // Check the element type. + if (getTypeInfoLinkage(AT->getElementType()) == + llvm::GlobalValue::InternalLinkage) + return llvm::GlobalValue::InternalLinkage; + } - llvm::SmallString<256> OutName; - CGM.getMangleContext().mangleCXXRTTI(Ty, OutName); - llvm::StringRef Name = OutName.str(); + } - llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Name); - if (GV && !GV->isDeclaration()) - return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); + return llvm::GlobalValue::WeakODRLinkage; +} - bool Extern = DecideExtern(Ty); - bool Hidden = DecideHidden(Ty); +// CanUseSingleInheritance - Return whether the given record decl has a "single, +// public, non-virtual base at offset zero (i.e. the derived class is dynamic +// iff the base is)", according to Itanium C++ ABI, 2.95p6b. +static bool CanUseSingleInheritance(const CXXRecordDecl *RD) { + // Check the number of bases. + if (RD->getNumBases() != 1) + return false; + + // Get the base. + CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(); + + // Check that the base is not virtual. + if (Base->isVirtual()) + return false; + + // Check that the base is public. + if (Base->getAccessSpecifier() != AS_public) + return false; + + // Check that the class is dynamic iff the base is. + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (!BaseDecl->isEmpty() && + BaseDecl->isDynamicClass() != RD->isDynamicClass()) + return false; + + return true; +} - const MemberPointerType *PtrMemTy = dyn_cast<MemberPointerType>(Ty); - QualType PointeeTy; - - if (PtrMemTy) - PointeeTy = PtrMemTy->getPointeeType(); - else - PointeeTy = Ty->getPointeeType(); - - if (PtrMemTy) - C = BuildVtableRef("_ZTVN10__cxxabiv129__pointer_to_member_type_infoE"); - else - C = BuildVtableRef("_ZTVN10__cxxabiv119__pointer_type_infoE"); - - info.push_back(C); - info.push_back(BuildName(Ty, Hidden, Extern)); - Qualifiers Q = PointeeTy.getQualifiers(); - - PointeeTy = - CGM.getContext().getCanonicalType(PointeeTy).getUnqualifiedType(); - - unsigned Flags = 0; - if (Q.hasConst()) - Flags |= TI_Const; - if (Q.hasVolatile()) - Flags |= TI_Volatile; - if (Q.hasRestrict()) - Flags |= TI_Restrict; +void RTTIBuilder::BuildVtablePointer(const Type *Ty) { + const char *VtableName; + + switch (Ty->getTypeClass()) { + default: assert(0 && "Unhandled type!"); + + // GCC treats vector types as fundamental types. + case Type::Vector: + case Type::ExtVector: + // abi::__fundamental_type_info. + VtableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE"; + break; + + case Type::ConstantArray: + case Type::IncompleteArray: + // abi::__array_type_info. + VtableName = "_ZTVN10__cxxabiv117__array_type_infoE"; + break; + + case Type::FunctionNoProto: + case Type::FunctionProto: + // abi::__function_type_info. + VtableName = "_ZTVN10__cxxabiv120__function_type_infoE"; + break; + + case Type::Enum: + // abi::__enum_type_info. + VtableName = "_ZTVN10__cxxabiv116__enum_type_infoE"; + break; + + case Type::Record: { + const CXXRecordDecl *RD = + cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl()); - if (Ty->isIncompleteType()) - Flags |= TI_Incomplete; - - if (PtrMemTy && PtrMemTy->getClass()->isIncompleteType()) - Flags |= TI_ContainingClassIncomplete; + if (!RD->getNumBases()) { + // abi::__class_type_info. + VtableName = "_ZTVN10__cxxabiv117__class_type_infoE"; + } else if (CanUseSingleInheritance(RD)) { + // abi::__si_class_type_info. + VtableName = "_ZTVN10__cxxabiv120__si_class_type_infoE"; + } else { + // abi::__vmi_class_type_info. + VtableName = "_ZTVN10__cxxabiv121__vmi_class_type_infoE"; + } - info.push_back(BuildInt(Flags)); - info.push_back(BuildInt(0)); - info.push_back(BuildType(PointeeTy)); + break; + } - if (PtrMemTy) - info.push_back(BuildType(QualType(PtrMemTy->getClass(), 0))); + case Type::Pointer: + // abi::__pointer_type_info. + VtableName = "_ZTVN10__cxxabiv119__pointer_type_infoE"; + break; - // We always generate these as hidden, only the name isn't hidden. - return finish(&info[0], info.size(), GV, Name, /*Hidden=*/true, - GetLinkageFromExternFlag(Extern)); + case Type::MemberPointer: + // abi::__pointer_to_member_type_info. + VtableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE"; + break; } - llvm::Constant *BuildSimpleType(QualType Ty, const char *vtbl) { - llvm::SmallString<256> OutName; - CGM.getMangleContext().mangleCXXRTTI(Ty, OutName); - llvm::StringRef Name = OutName.str(); + llvm::Constant *Vtable = + CGM.getModule().getOrInsertGlobal(VtableName, Int8PtrTy); + + const llvm::Type *PtrDiffTy = + CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); + + // The vtable address point is 2. + llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2); + Vtable = llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, &Two, 1); + Vtable = llvm::ConstantExpr::getBitCast(Vtable, Int8PtrTy); - llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Name); - if (GV && !GV->isDeclaration()) - return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); + Fields.push_back(Vtable); +} - bool Extern = DecideExtern(Ty); - bool Hidden = DecideHidden(Ty); +llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty) { + // We want to operate on the canonical type. + Ty = CGM.getContext().getCanonicalType(Ty); - llvm::Constant *Info[] = { - BuildVtableRef(vtbl), BuildName(Ty, Hidden, Extern) - }; + // Check if we've already emitted an RTTI descriptor for this type. + llvm::SmallString<256> OutName; + CGM.getMangleContext().mangleCXXRTTI(Ty, OutName); + llvm::StringRef Name = OutName.str(); + + llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name); + if (OldGV && !OldGV->isDeclaration()) + return llvm::ConstantExpr::getBitCast(OldGV, Int8PtrTy); + + // Check if there is already an external RTTI descriptor for this type. + if (ShouldUseExternalRTTIDescriptor(Ty)) + return GetAddrOfExternalRTTIDescriptor(Ty); + + llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(Ty); + + // Add the vtable pointer. + BuildVtablePointer(cast<Type>(Ty)); + + // And the name. + Fields.push_back(BuildName(Ty, DecideHidden(Ty), Linkage)); + + switch (Ty->getTypeClass()) { + default: assert(false && "Unhandled type class!"); + case Type::Builtin: + assert(false && "Builtin type info must be in the standard library!"); + break; + + // GCC treats vector types as fundamental types. + case Type::Vector: + case Type::ExtVector: + // Itanium C++ ABI 2.9.5p4: + // abi::__fundamental_type_info adds no data members to std::type_info. + break; + + case Type::ConstantArray: + case Type::IncompleteArray: + // Itanium C++ ABI 2.9.5p5: + // abi::__array_type_info adds no data members to std::type_info. + break; + + case Type::FunctionNoProto: + case Type::FunctionProto: + // Itanium C++ ABI 2.9.5p5: + // abi::__function_type_info adds no data members to std::type_info. + break; + + case Type::Enum: + // Itanium C++ ABI 2.9.5p5: + // abi::__enum_type_info adds no data members to std::type_info. + break; + + case Type::Record: { + const CXXRecordDecl *RD = + cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl()); + if (!RD->getNumBases()) { + // We don't need to emit any fields. + break; + } - // We always generate these as hidden, only the name isn't hidden. - return finish(&Info[0], llvm::array_lengthof(Info), GV, Name, - /*Hidden=*/true, GetLinkageFromExternFlag(Extern)); + if (CanUseSingleInheritance(RD)) + BuildSIClassTypeInfo(RD); + else + BuildVMIClassTypeInfo(RD); + + break; + } + + case Type::Pointer: + BuildPointerTypeInfo(cast<PointerType>(Ty)); + break; + + case Type::MemberPointer: + BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty)); + break; } - /// BuildType - Builds the type info for the given type. - llvm::Constant *BuildType(QualType Ty) { - const clang::Type &Type - = *CGM.getContext().getCanonicalType(Ty).getTypePtr(); + llvm::Constant *Init = + llvm::ConstantStruct::get(VMContext, &Fields[0], Fields.size(), + /*Packed=*/false); - if (const RecordType *RT = Ty.getTypePtr()->getAs<RecordType>()) - if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl())) - return BuildClassTypeInfo(RD); + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(CGM.getModule(), Init->getType(), + /*Constant=*/true, Linkage, Init, Name); + + // If there's already an old global variable, replace it with the new one. + if (OldGV) { + GV->takeName(OldGV); + llvm::Constant *NewPtr = + llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); + OldGV->replaceAllUsesWith(NewPtr); + OldGV->eraseFromParent(); + } + + return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); +} - switch (Type.getTypeClass()) { - default: { - assert(0 && "typeid expression"); - return llvm::Constant::getNullValue(Int8PtrTy); - } +/// ComputeQualifierFlags - Compute the pointer type info flags from the +/// given qualifier. +static unsigned ComputeQualifierFlags(Qualifiers Quals) { + unsigned Flags = 0; - case Type::Builtin: { - // We expect all type_info objects for builtin types to be in the library. - return BuildTypeRef(Ty); - } + if (Quals.hasConst()) + Flags |= RTTIBuilder::PTI_Const; + if (Quals.hasVolatile()) + Flags |= RTTIBuilder::PTI_Volatile; + if (Quals.hasRestrict()) + Flags |= RTTIBuilder::PTI_Restrict; + + return Flags; +} - case Type::Pointer: { - QualType PTy = Ty->getPointeeType(); - Qualifiers Q = PTy.getQualifiers(); - Q.removeConst(); - // T* and const T* for all builtin types T are expected in the library. - if (isa<BuiltinType>(PTy) && Q.empty()) - return BuildTypeRef(Ty); +/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single +/// inheritance, according to the Itanium C++ ABI, 2.95p6b. +void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) { + // Itanium C++ ABI 2.9.5p6b: + // It adds to abi::__class_type_info a single member pointing to the + // type_info structure for the base type, + llvm::Constant *BaseTypeInfo = + RTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType()); + Fields.push_back(BaseTypeInfo); +} + +/// SeenBases - Contains virtual and non-virtual bases seen when traversing +/// a class hierarchy. +struct SeenBases { + llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases; + llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases; +}; - return BuildPointerType(Ty); +/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in +/// abi::__vmi_class_type_info. +/// +static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base, + SeenBases &Bases) { + + unsigned Flags = 0; + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + + if (Base->isVirtual()) { + if (Bases.VirtualBases.count(BaseDecl)) { + // If this virtual base has been seen before, then the class is diamond + // shaped. + Flags |= RTTIBuilder::VMI_DiamondShaped; + } else { + if (Bases.NonVirtualBases.count(BaseDecl)) + Flags |= RTTIBuilder::VMI_NonDiamondRepeat; + + // Mark the virtual base as seen. + Bases.VirtualBases.insert(BaseDecl); } - case Type::MemberPointer: - return BuildPointerType(Ty); - case Type::FunctionProto: - case Type::FunctionNoProto: - return BuildSimpleType(Ty, "_ZTVN10__cxxabiv120__function_type_infoE"); - case Type::ConstantArray: - case Type::IncompleteArray: - case Type::VariableArray: - case Type::Vector: - case Type::ExtVector: - return BuildSimpleType(Ty, "_ZTVN10__cxxabiv117__array_type_infoE"); - case Type::Enum: - return BuildSimpleType(Ty, "_ZTVN10__cxxabiv116__enum_type_infoE"); + } else { + if (Bases.NonVirtualBases.count(BaseDecl)) { + // If this non-virtual base has been seen before, then the class has non- + // diamond shaped repeated inheritance. + Flags |= RTTIBuilder::VMI_NonDiamondRepeat; + } else { + if (Bases.VirtualBases.count(BaseDecl)) + Flags |= RTTIBuilder::VMI_NonDiamondRepeat; + + // Mark the non-virtual base as seen. + Bases.NonVirtualBases.insert(BaseDecl); } } + + // Walk all bases. + for (CXXRecordDecl::base_class_const_iterator I = BaseDecl->bases_begin(), + E = BaseDecl->bases_end(); I != E; ++I) + Flags |= ComputeVMIClassTypeInfoFlags(I, Bases); - /// BuildClassTypeInfo - Builds the class type info (or a reference to it) - /// for the given record decl. - llvm::Constant *BuildClassTypeInfo(const CXXRecordDecl *RD) { - const CXXMethodDecl *KeyFunction = 0; + return Flags; +} - if (RD->isDynamicClass()) - KeyFunction = CGM.getContext().getKeyFunction(RD); +static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) { + unsigned Flags = 0; + SeenBases Bases; + + // Walk all bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) + Flags |= ComputeVMIClassTypeInfoFlags(I, Bases); + + return Flags; +} + +/// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for +/// classes with bases that do not satisfy the abi::__si_class_type_info +/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c. +void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { + const llvm::Type *UnsignedIntLTy = + CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); + + // Itanium C++ ABI 2.9.5p6c: + // __flags is a word with flags describing details about the class + // structure, which may be referenced by using the __flags_masks + // enumeration. These flags refer to both direct and indirect bases. + unsigned Flags = ComputeVMIClassTypeInfoFlags(RD); + Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); + + // Itanium C++ ABI 2.9.5p6c: + // __base_count is a word with the number of direct proper base class + // descriptions that follow. + Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases())); + + if (!RD->getNumBases()) + return; + + const llvm::Type *LongLTy = + CGM.getTypes().ConvertType(CGM.getContext().LongTy); + + // Now add the base class descriptions. + + // Itanium C++ ABI 2.9.5p6c: + // __base_info[] is an array of base class descriptions -- one for every + // direct proper base. Each description is of the type: + // + // struct abi::__base_class_type_info { + // public: + // const __class_type_info *__base_type; + // long __offset_flags; + // + // enum __offset_flags_masks { + // __virtual_mask = 0x1, + // __public_mask = 0x2, + // __offset_shift = 8 + // }; + // }; + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXBaseSpecifier *Base = I; + + // The __base_type member points to the RTTI for the base type. + Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(Base->getType())); + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + + int64_t OffsetFlags = 0; - if (KeyFunction) { - // If the key function is defined in this translation unit, then the RTTI - // related constants should also be emitted here, with external linkage. - if (KeyFunction->getBody()) - return Buildclass_type_info(RD, llvm::GlobalValue::ExternalLinkage); - - // Otherwise, we just want a reference to the type info. - return Buildclass_type_infoRef(RD); - } + // All but the lower 8 bits of __offset_flags are a signed offset. + // For a non-virtual base, this is the offset in the object of the base + // subobject. For a virtual base, this is the offset in the virtual table of + // the virtual base offset for the virtual base referenced (negative). + if (Base->isVirtual()) + OffsetFlags = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, BaseDecl); + else { + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + OffsetFlags = Layout.getBaseClassOffset(BaseDecl) / 8; + }; + + OffsetFlags <<= 8; - // If there is no key function (or if the record doesn't have any virtual - // member functions or virtual bases), emit the type info with weak_odr - // linkage. - return Buildclass_type_info(RD, llvm::GlobalValue::WeakODRLinkage); + // The low-order byte of __offset_flags contains flags, as given by the + // masks from the enumeration __offset_flags_masks. + if (Base->isVirtual()) + OffsetFlags |= BCTI_Virtual; + if (Base->getAccessSpecifier() == AS_public) + OffsetFlags |= BCTI_Public; + + Fields.push_back(llvm::ConstantInt::get(LongLTy, OffsetFlags)); } -}; } -llvm::Constant *CodeGenModule::GetAddrOfRTTI(const CXXRecordDecl *RD) { - if (!getContext().getLangOptions().RTTI) { - const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); - return llvm::Constant::getNullValue(Int8PtrTy); - } +/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, +/// used for pointer types. +void RTTIBuilder::BuildPointerTypeInfo(const PointerType *Ty) { + QualType PointeeTy = Ty->getPointeeType(); - return RTTIBuilder(*this).BuildClassTypeInfo(RD); -} - -llvm::Constant *CodeGenModule::GetAddrOfRTTI(QualType Ty) { - if (!getContext().getLangOptions().RTTI) { - const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); - return llvm::Constant::getNullValue(Int8PtrTy); - } + // Itanium C++ ABI 2.9.5p7: + // __flags is a flag word describing the cv-qualification and other + // attributes of the type pointed to + unsigned Flags = ComputeQualifierFlags(PointeeTy.getQualifiers()); + + // Itanium C++ ABI 2.9.5p7: + // When the abi::__pbase_type_info is for a direct or indirect pointer to an + // incomplete class type, the incomplete target type flag is set. + if (ContainsIncompleteClassType(PointeeTy)) + Flags |= PTI_Incomplete; + + const llvm::Type *UnsignedIntLTy = + CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); + Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); - return RTTIBuilder(*this).BuildType(Ty); + // Itanium C++ ABI 2.9.5p7: + // __pointee is a pointer to the std::type_info derivation for the + // unqualified type being pointed to. + llvm::Constant *PointeeTypeInfo = + RTTIBuilder(CGM).BuildTypeInfo(PointeeTy.getUnqualifiedType()); + Fields.push_back(PointeeTypeInfo); } -llvm::Constant *CodeGenModule::GenerateRTTIRef(const CXXRecordDecl *RD) { - RTTIBuilder b(*this); +/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info +/// struct, used for member pointer types. +void RTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { + QualType PointeeTy = Ty->getPointeeType(); + + // Itanium C++ ABI 2.9.5p7: + // __flags is a flag word describing the cv-qualification and other + // attributes of the type pointed to. + unsigned Flags = ComputeQualifierFlags(PointeeTy.getQualifiers()); - return b.Buildclass_type_infoRef(RD); -} + const RecordType *ClassType = cast<RecordType>(Ty->getClass()); -llvm::Constant *CodeGenModule::GenerateRTTI(const CXXRecordDecl *RD) { - RTTIBuilder b(*this); + // Itanium C++ ABI 2.9.5p7: + // When the abi::__pbase_type_info is for a direct or indirect pointer to an + // incomplete class type, the incomplete target type flag is set. + if (ContainsIncompleteClassType(PointeeTy)) + Flags |= PTI_Incomplete; - return b.Buildclass_type_info(RD, llvm::GlobalValue::ExternalLinkage); + if (IsIncompleteClassType(ClassType)) + Flags |= PTI_ContainingClassIncomplete; + + const llvm::Type *UnsignedIntLTy = + CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); + Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); + + // Itanium C++ ABI 2.9.5p7: + // __pointee is a pointer to the std::type_info derivation for the + // unqualified type being pointed to. + llvm::Constant *PointeeTypeInfo = + RTTIBuilder(CGM).BuildTypeInfo(PointeeTy.getUnqualifiedType()); + Fields.push_back(PointeeTypeInfo); + + // Itanium C++ ABI 2.9.5p9: + // __context is a pointer to an abi::__class_type_info corresponding to the + // class type containing the member pointed to + // (e.g., the "A" in "int A::*"). + Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0))); } -llvm::Constant *CodeGenModule::GenerateRTTI(QualType Ty) { - RTTIBuilder b(*this); - - return b.BuildType(Ty); +llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty) { + if (!getContext().getLangOptions().RTTI) { + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); + return llvm::Constant::getNullValue(Int8PtrTy); + } + + return RTTIBuilder(*this).BuildTypeInfo(Ty); } diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 31784ed..9f90ec5 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -216,12 +216,28 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { AppendPadding(Layout.getSize() / 8, Align); } +void CGRecordLayoutBuilder::LayoutBases(const CXXRecordDecl *RD, + const ASTRecordLayout &Layout) { + // Check if we need to add a vtable pointer. + if (RD->isDynamicClass() && !Layout.getPrimaryBase()) { + const llvm::Type *Int8PtrTy = + llvm::Type::getInt8PtrTy(Types.getLLVMContext()); + + assert(NextFieldOffsetInBytes == 0 && + "Vtable pointer must come first!"); + AppendField(NextFieldOffsetInBytes, Int8PtrTy->getPointerTo()); + } +} + bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { assert(!D->isUnion() && "Can't call LayoutFields on a union!"); assert(Alignment && "Did not set alignment!"); const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D); + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) + LayoutBases(RD, Layout); + unsigned FieldNo = 0; for (RecordDecl::field_iterator Field = D->field_begin(), diff --git a/lib/CodeGen/CGRecordLayoutBuilder.h b/lib/CodeGen/CGRecordLayoutBuilder.h index 4ebf4e8..cf84053 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.h +++ b/lib/CodeGen/CGRecordLayoutBuilder.h @@ -23,6 +23,8 @@ namespace llvm { } namespace clang { + class ASTRecordLayout; + class CXXRecordDecl; class FieldDecl; class RecordDecl; @@ -90,6 +92,9 @@ class CGRecordLayoutBuilder { /// Returns false if the operation failed because the struct is not packed. bool LayoutFields(const RecordDecl *D); + /// LayoutBases - layout the bases and vtable pointer of a record decl. + void LayoutBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout); + /// LayoutField - layout a single field. Returns false if the operation failed /// because the current struct is not packed. bool LayoutField(const FieldDecl *D, uint64_t FieldOffset); diff --git a/lib/CodeGen/CGTemporaries.cpp b/lib/CodeGen/CGTemporaries.cpp index 5cfc7ef..bed8439 100644 --- a/lib/CodeGen/CGTemporaries.cpp +++ b/lib/CodeGen/CGTemporaries.cpp @@ -17,6 +17,10 @@ using namespace CodeGen; void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary, llvm::Value *Ptr) { + assert((LiveTemporaries.empty() || + LiveTemporaries.back().ThisPtr != Ptr || + ConditionalBranchLevel) && + "Pushed the same temporary twice; AST is likely wrong"); llvm::BasicBlock *DtorBlock = createBasicBlock("temp.dtor"); llvm::Value *CondPtr = 0; @@ -41,6 +45,33 @@ void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary, CondPtr)); PushCleanupBlock(DtorBlock); + + if (Exceptions) { + const CXXLiveTemporaryInfo& Info = LiveTemporaries.back(); + llvm::BasicBlock *CondEnd = 0; + + EHCleanupBlock Cleanup(*this); + + // If this is a conditional temporary, we need to check the condition + // boolean and only call the destructor if it's true. + if (Info.CondPtr) { + llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call"); + CondEnd = createBasicBlock("cond.dtor.end"); + + llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr); + Builder.CreateCondBr(Cond, CondBlock, CondEnd); + EmitBlock(CondBlock); + } + + EmitCXXDestructorCall(Info.Temporary->getDestructor(), + Dtor_Complete, Info.ThisPtr); + + if (CondEnd) { + // Reset the condition. to false. + Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr); + EmitBlock(CondEnd); + } + } } void CodeGenFunction::PopCXXTemporary() { @@ -92,12 +123,6 @@ CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, llvm::Value *AggLoc, bool IsAggLocVolatile, bool IsInitializer) { - // If we shouldn't destroy the temporaries, just emit the - // child expression. - if (!E->shouldDestroyTemporaries()) - return EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile, - /*IgnoreResult=*/false, IsInitializer); - // Keep track of the current cleanup stack depth. size_t CleanupStackDepth = CleanupEntries.size(); (void) CleanupStackDepth; @@ -119,11 +144,6 @@ CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue( const CXXExprWithTemporaries *E) { - // If we shouldn't destroy the temporaries, just emit the - // child expression. - if (!E->shouldDestroyTemporaries()) - return EmitLValue(E->getSubExpr()); - // Keep track of the current cleanup stack depth. size_t CleanupStackDepth = CleanupEntries.size(); (void) CleanupStackDepth; diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 5283ed9..7930f71 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/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. @@ -481,13 +483,13 @@ public: } - Index_t FinishGenerateVtable(const CXXRecordDecl *RD, - const ASTRecordLayout &Layout, - const CXXRecordDecl *PrimaryBase, - bool PrimaryBaseWasVirtual, - bool MorallyVirtual, int64_t Offset, - bool ForVirtualBase, int64_t CurrentVBaseOffset, - Path_t *Path) { + void FinishGenerateVtable(const CXXRecordDecl *RD, + const ASTRecordLayout &Layout, + const CXXRecordDecl *PrimaryBase, + bool PrimaryBaseWasVirtual, + bool MorallyVirtual, int64_t Offset, + bool ForVirtualBase, int64_t CurrentVBaseOffset, + Path_t *Path) { bool alloc = false; if (Path == 0) { alloc = true; @@ -535,7 +537,6 @@ public: if (alloc) { delete Path; } - return AddressPoint; } void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset, @@ -600,19 +601,19 @@ public: } } - int64_t GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0, - bool MorallyVirtual = false, - bool ForVirtualBase = false, - int CurrentVBaseOffset = 0, - Path_t *Path = 0) { + void GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0, + bool MorallyVirtual = false, + bool ForVirtualBase = false, + int CurrentVBaseOffset = 0, + Path_t *Path = 0) { if (!RD->isDynamicClass()) - return 0; + return; // Construction vtable don't need parts that have no virtual bases and // aren't morally virtual. if ((LayoutClass != MostDerivedClass) && RD->getNumVBases() == 0 && !MorallyVirtual) - return 0; + return; const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); @@ -631,9 +632,9 @@ public: if (Path) OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset); - return FinishGenerateVtable(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, - MorallyVirtual, Offset, ForVirtualBase, - CurrentVBaseOffset, Path); + FinishGenerateVtable(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, + MorallyVirtual, Offset, ForVirtualBase, + CurrentVBaseOffset, Path); } void GenerateVtableForVBases(const CXXRecordDecl *RD, @@ -751,10 +752,10 @@ TypeConversionRequiresAdjustment(ASTContext &Ctx, } const CXXRecordDecl *DerivedDecl = - cast<CXXRecordDecl>(cast<RecordType>(CanDerivedType)->getDecl()); + cast<CXXRecordDecl>(cast<RecordType>(CanDerivedType)->getDecl()); const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(cast<RecordType>(CanBaseType)->getDecl()); + cast<CXXRecordDecl>(cast<RecordType>(CanBaseType)->getDecl()); return TypeConversionRequiresAdjustment(Ctx, DerivedDecl, BaseDecl); } @@ -1156,22 +1157,13 @@ CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage, CGM.getMangleContext().mangleCXXVtable(RD, OutName); llvm::StringRef Name = OutName.str(); - int64_t AddressPoint; - llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); - if (GV && CGM.AddressPoints[LayoutClass] && !GV->isDeclaration()) { - AddressPoint=(*(*(CGM.AddressPoints[LayoutClass]))[RD])[std::make_pair(RD, - Offset)]; - // FIXME: We can never have 0 address point. Do this for now so gepping - // retains the same structure. Later, we'll just assert. - if (AddressPoint == 0) - AddressPoint = 1; - } else { + if (GV == 0 || CGM.AddressPoints[LayoutClass] == 0 || GV->isDeclaration()) { VtableBuilder b(RD, LayoutClass, Offset, CGM, GenerateDefinition); D1(printf("vtable %s\n", RD->getNameAsCString())); // First comes the vtables for all the non-virtual bases... - AddressPoint = b.GenerateVtableForBase(RD, Offset); + b.GenerateVtableForBase(RD, Offset); // then the vtables for all the virtual bases. b.GenerateVtableForVBases(RD, Offset); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 28df9e4..f904f04 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -331,7 +331,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { // FIXME: For C++0x, we want to look for implicit *definitions* of // these special member functions, rather than implicit *declarations*. - if (CD->isCopyConstructor(getContext())) { + if (CD->isCopyConstructor()) { assert(!ClassDecl->hasUserDeclaredCopyConstructor() && "Cannot synthesize a non-implicit copy constructor"); SynthesizeCXXCopyConstructor(CD, GD.getCtorType(), Fn, Args); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 12e636c..273ddca 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -515,6 +515,12 @@ public: void InitializeVtablePtrs(const CXXRecordDecl *ClassDecl); + void InitializeVtablePtrsRecursive(const CXXRecordDecl *ClassDecl, + llvm::Constant *Vtable, + CodeGenModule::AddrSubMap_t& AddressPoints, + llvm::Value *ThisPtr, + uint64_t Offset); + void SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, CXXCtorType Type, llvm::Function *Fn, @@ -807,6 +813,8 @@ public: llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E); llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE); + void EmitCheck(llvm::Value *, unsigned Size); + //===--------------------------------------------------------------------===// // Declaration Emission //===--------------------------------------------------------------------===// @@ -921,6 +929,12 @@ public: /// LValue EmitLValue(const Expr *E); + /// EmitCheckedLValue - Same as EmitLValue but additionally we generate + /// checking code to guard against undefined behavior. This is only + /// suitable when we know that the address will be used to access the + /// object. + LValue EmitCheckedLValue(const Expr *E); + /// EmitLoadOfScalar - Load a scalar value from an address, taking /// care to appropriately convert from the memory representation to /// the LLVM value representation. @@ -1022,14 +1036,17 @@ public: /// used to set attributes on the call (noreturn, etc.). RValue EmitCall(const CGFunctionInfo &FnInfo, llvm::Value *Callee, + ReturnValueSlot ReturnValue, const CallArgList &Args, const Decl *TargetDecl = 0); - RValue EmitCall(llvm::Value *Callee, QualType FnType, + RValue EmitCall(QualType FnType, llvm::Value *Callee, + ReturnValueSlot ReturnValue, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, const Decl *TargetDecl = 0); - RValue EmitCallExpr(const CallExpr *E); + RValue EmitCallExpr(const CallExpr *E, + ReturnValueSlot ReturnValue = ReturnValueSlot()); llvm::Value *BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This, const llvm::Type *Ty); @@ -1038,20 +1055,24 @@ public: RValue EmitCXXMemberCall(const CXXMethodDecl *MD, llvm::Value *Callee, + ReturnValueSlot ReturnValue, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd); - RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E); - RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E); + RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E, + ReturnValueSlot ReturnValue); + RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, + ReturnValueSlot ReturnValue); RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, - const CXXMethodDecl *MD); + const CXXMethodDecl *MD, + ReturnValueSlot ReturnValue); RValue EmitBuiltinExpr(const FunctionDecl *FD, unsigned BuiltinID, const CallExpr *E); - RValue EmitBlockCallExpr(const CallExpr *E); + RValue EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue); /// EmitTargetBuiltinExpr - Emit the given builtin call. Returns 0 if the call /// is unhandled by the current target. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 761f343..d497471 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -30,6 +30,7 @@ #include "llvm/CallingConv.h" #include "llvm/Module.h" #include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" #include "llvm/Target/TargetData.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -546,7 +547,7 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { // static, static inline, always_inline, and extern inline functions can // always be deferred. Normal inline functions can be deferred in C99/C++. if (Linkage == GVA_Internal || Linkage == GVA_C99Inline || - Linkage == GVA_CXXInline) + Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation) return true; return false; } @@ -1089,9 +1090,8 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, CI->replaceAllUsesWith(NewCall); // Copy any custom metadata attached with CI. - llvm::MetadataContext &TheMetadata = CI->getContext().getMetadata(); - TheMetadata.copyMD(CI, NewCall); - + if (llvm::MDNode *DbgNode = CI->getMetadata("dbg")) + NewCall->setMetadata("dbg", DbgNode); CI->eraseFromParent(); } } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index cc7ec9c..939c66c 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -212,24 +212,10 @@ 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); + /// GetAddrOfRTTIDescriptor - Get the address of the RTTI descriptor + /// for the given type. + llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty); - /// GetAddrOfRTTI - Get the address of the RTTI structure for the given record - /// decl. - llvm::Constant *GetAddrOfRTTI(const CXXRecordDecl *RD); - - /// GenerateRTTI - Generate the rtti information for the given type. - llvm::Constant *GenerateRTTI(const CXXRecordDecl *RD); - - /// GenerateRTTIRef - Generate a reference to the rtti information for the - /// given type. - llvm::Constant *GenerateRTTIRef(const CXXRecordDecl *RD); - - /// GenerateRTTI - Generate the rtti information for the given - /// non-class type. - llvm::Constant *GenerateRTTI(QualType Ty); - llvm::Constant *GetAddrOfThunk(GlobalDecl GD, const ThunkAdjustment &ThisAdjustment); llvm::Constant *GetAddrOfCovariantThunk(GlobalDecl GD, @@ -247,8 +233,8 @@ public: const CovariantThunkAdjustment &Adjustment); typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t; - typedef llvm::DenseMap<const CXXRecordDecl *, - llvm::DenseMap<CtorVtable_t, int64_t>*> AddrMap_t; + typedef llvm::DenseMap<CtorVtable_t, int64_t> AddrSubMap_t; + typedef llvm::DenseMap<const CXXRecordDecl *, AddrSubMap_t *> AddrMap_t; llvm::DenseMap<const CXXRecordDecl *, AddrMap_t*> AddressPoints; /// GetCXXBaseClassOffset - Returns the offset from a derived class to its diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index cd3575c..cd34e0c 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -199,7 +199,6 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { case Type::Builtin: { switch (cast<BuiltinType>(Ty).getKind()) { - default: assert(0 && "Unknown builtin type!"); case BuiltinType::Void: case BuiltinType::ObjCId: case BuiltinType::ObjCClass: @@ -245,12 +244,16 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { case BuiltinType::UInt128: case BuiltinType::Int128: return llvm::IntegerType::get(getLLVMContext(), 128); + + case BuiltinType::Overload: + case BuiltinType::Dependent: + case BuiltinType::UndeducedAuto: + assert(0 && "Unexpected builtin type!"); + break; } + assert(0 && "Unknown builtin type!"); break; } - case Type::FixedWidthInt: - return llvm::IntegerType::get(getLLVMContext(), - cast<FixedWidthIntType>(T)->getWidth()); case Type::Complex: { const llvm::Type *EltTy = ConvertTypeRecursive(cast<ComplexType>(Ty).getElementType()); diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 90cc894..10fd1f5 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -125,8 +125,8 @@ private: void mangleTemplateArgs(const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); - void mangleTemplateArgumentList(const TemplateArgumentList &L); - void mangleTemplateArgument(const TemplateArgument &A); + void mangleTemplateArgs(const TemplateArgumentList &L); + void mangleTemplateArg(const TemplateArgument &A); void mangleTemplateParameter(unsigned Index); }; @@ -321,7 +321,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { const TemplateArgumentList *TemplateArgs = 0; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleUnscopedTemplateName(TD); - mangleTemplateArgumentList(*TemplateArgs); + mangleTemplateArgs(*TemplateArgs); return; } @@ -480,10 +480,17 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { mangleType(Context.getASTContext().getCanonicalType(Name.getCXXNameType())); break; - case DeclarationName::CXXOperatorName: - mangleOperatorName(Name.getCXXOverloadedOperator(), - cast<FunctionDecl>(ND)->getNumParams()); + case DeclarationName::CXXOperatorName: { + unsigned Arity = cast<FunctionDecl>(ND)->getNumParams(); + + // If we have a C++ member function, we need to include the 'this' pointer. + // FIXME: This does not make sense for operators that are static, but their + // names stay the same regardless of the arity (operator new for instance). + if (isa<CXXMethodDecl>(ND)) + Arity++; + mangleOperatorName(Name.getCXXOverloadedOperator(), Arity); break; + } case DeclarationName::CXXLiteralOperatorName: // FIXME: This mangling is not yet official. @@ -517,7 +524,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, const TemplateArgumentList *TemplateArgs = 0; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); - mangleTemplateArgumentList(*TemplateArgs); + mangleTemplateArgs(*TemplateArgs); } else { manglePrefix(DC); mangleUnqualifiedName(ND); @@ -573,7 +580,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC) { const TemplateArgumentList *TemplateArgs = 0; if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) { mangleTemplatePrefix(TD); - mangleTemplateArgumentList(*TemplateArgs); + mangleTemplateArgs(*TemplateArgs); } else { manglePrefix(DC->getParent()); mangleUnqualifiedName(cast<NamedDecl>(DC)); @@ -611,16 +618,24 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { case OO_Array_Delete: Out << "da"; break; // ::= ps # + (unary) // ::= pl # + - case OO_Plus: Out << (Arity == 1? "ps" : "pl"); break; + case OO_Plus: + assert((Arity == 1 || Arity == 2) && "Invalid arity!"); + Out << (Arity == 1? "ps" : "pl"); break; // ::= ng # - (unary) // ::= mi # - - case OO_Minus: Out << (Arity == 1? "ng" : "mi"); break; + case OO_Minus: + assert((Arity == 1 || Arity == 2) && "Invalid arity!"); + Out << (Arity == 1? "ng" : "mi"); break; // ::= ad # & (unary) // ::= an # & - case OO_Amp: Out << (Arity == 1? "ad" : "an"); break; + case OO_Amp: + assert((Arity == 1 || Arity == 2) && "Invalid arity!"); + Out << (Arity == 1? "ad" : "an"); break; // ::= de # * (unary) // ::= ml # * - case OO_Star: Out << (Arity == 1? "de" : "ml"); break; + case OO_Star: + assert((Arity == 1 || Arity == 2) && "Invalid arity!"); + Out << (Arity == 1? "de" : "ml"); break; // ::= co # ~ case OO_Tilde: Out << "co"; break; // ::= dv # / @@ -975,11 +990,8 @@ void CXXNameMangler::mangleType(const ObjCInterfaceType *T) { } void CXXNameMangler::mangleType(const BlockPointerType *T) { - assert(false && "can't mangle block pointer types yet"); -} - -void CXXNameMangler::mangleType(const FixedWidthIntType *T) { - assert(false && "can't mangle arbitary-precision integer type yet"); + Out << "U13block_pointer"; + mangleType(T->getPointeeType()); } void CXXNameMangler::mangleType(const TemplateSpecializationType *T) { @@ -1078,6 +1090,16 @@ void CXXNameMangler::mangleExpression(const Expr *E) { break; } + case Expr::CXXOperatorCallExprClass: { + const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E); + unsigned NumArgs = CE->getNumArgs(); + mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs); + // Mangle the arguments. + for (unsigned i = 0; i != NumArgs; ++i) + mangleExpression(CE->getArg(i)); + break; + } + case Expr::ParenExprClass: mangleExpression(cast<ParenExpr>(E)->getSubExpr()); break; @@ -1161,11 +1183,11 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { } } -void CXXNameMangler::mangleTemplateArgumentList(const TemplateArgumentList &L) { +void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &L) { // <template-args> ::= I <template-arg>+ E Out << "I"; for (unsigned i = 0, e = L.size(); i != e; ++i) - mangleTemplateArgument(L[i]); + mangleTemplateArg(L[i]); Out << "E"; } @@ -1174,11 +1196,11 @@ void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs, // <template-args> ::= I <template-arg>+ E Out << "I"; for (unsigned i = 0; i != NumTemplateArgs; ++i) - mangleTemplateArgument(TemplateArgs[i]); + mangleTemplateArg(TemplateArgs[i]); Out << "E"; } -void CXXNameMangler::mangleTemplateArgument(const TemplateArgument &A) { +void CXXNameMangler::mangleTemplateArg(const TemplateArgument &A) { // <template-arg> ::= <type> # type or template // ::= X <expression> E # expression // ::= <expr-primary> # simple expressions @@ -1190,6 +1212,9 @@ void CXXNameMangler::mangleTemplateArgument(const TemplateArgument &A) { case TemplateArgument::Type: mangleType(A.getAsType()); break; + case TemplateArgument::Template: + mangleName(A.getAsTemplate().getAsTemplateDecl()); + break; case TemplateArgument::Expression: Out << 'X'; mangleExpression(A.getAsExpr()); @@ -1558,6 +1583,7 @@ void MangleContext::mangleCXXCtorVtable(const CXXRecordDecl *RD, int64_t Offset, void MangleContext::mangleCXXRTTI(QualType Ty, llvm::SmallVectorImpl<char> &Res) { // <special-name> ::= TI <type> # typeinfo structure + assert(!Ty.hasQualifiers() && "RTTI info cannot have top-level qualifiers"); CXXNameMangler Mangler(*this, Res); Mangler.getStream() << "_ZTI"; Mangler.mangleType(Ty); diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index 017059d..1e1edc1 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -81,7 +81,7 @@ namespace { if (Builder) Builder->Release(); - }; + } virtual void CompleteTentativeDefinition(VarDecl *D) { if (Diags.hasErrorOccurred()) diff --git a/lib/CodeGen/TargetABIInfo.cpp b/lib/CodeGen/TargetABIInfo.cpp index 7be1ead..863a297 100644 --- a/lib/CodeGen/TargetABIInfo.cpp +++ b/lib/CodeGen/TargetABIInfo.cpp @@ -805,6 +805,10 @@ void X86_64ABIInfo::classify(QualType Ty, if (Lo == Memory || Hi == Memory) break; } + + // If this record has no fields but isn't empty, classify as INTEGER. + if (RD->field_empty() && Size) + Current = Integer; } // Classify the fields one at a time, merging the results. |