1f22ef01cSRoman Divacky //===--- CGExprAgg.cpp - Emit LLVM Code from Aggregate Expressions --------===// 2f22ef01cSRoman Divacky // 3f22ef01cSRoman Divacky // The LLVM Compiler Infrastructure 4f22ef01cSRoman Divacky // 5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source 6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details. 7f22ef01cSRoman Divacky // 8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 9f22ef01cSRoman Divacky // 10f22ef01cSRoman Divacky // This contains code to emit Aggregate Expr nodes as LLVM code. 11f22ef01cSRoman Divacky // 12f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 13f22ef01cSRoman Divacky 14f22ef01cSRoman Divacky #include "CodeGenFunction.h" 15f22ef01cSRoman Divacky #include "CodeGenModule.h" 16f22ef01cSRoman Divacky #include "CGObjCRuntime.h" 17f22ef01cSRoman Divacky #include "clang/AST/ASTContext.h" 18f22ef01cSRoman Divacky #include "clang/AST/DeclCXX.h" 19dff0c46cSDimitry Andric #include "clang/AST/DeclTemplate.h" 20f22ef01cSRoman Divacky #include "clang/AST/StmtVisitor.h" 21f22ef01cSRoman Divacky #include "llvm/Constants.h" 22f22ef01cSRoman Divacky #include "llvm/Function.h" 23f22ef01cSRoman Divacky #include "llvm/GlobalVariable.h" 24f22ef01cSRoman Divacky #include "llvm/Intrinsics.h" 25f22ef01cSRoman Divacky using namespace clang; 26f22ef01cSRoman Divacky using namespace CodeGen; 27f22ef01cSRoman Divacky 28f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 29f22ef01cSRoman Divacky // Aggregate Expression Emitter 30f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 31f22ef01cSRoman Divacky 32f22ef01cSRoman Divacky namespace { 33f22ef01cSRoman Divacky class AggExprEmitter : public StmtVisitor<AggExprEmitter> { 34f22ef01cSRoman Divacky CodeGenFunction &CGF; 35f22ef01cSRoman Divacky CGBuilderTy &Builder; 362754fe60SDimitry Andric AggValueSlot Dest; 37f22ef01cSRoman Divacky bool IgnoreResult; 38f22ef01cSRoman Divacky 396122f3e6SDimitry Andric /// We want to use 'dest' as the return slot except under two 406122f3e6SDimitry Andric /// conditions: 416122f3e6SDimitry Andric /// - The destination slot requires garbage collection, so we 426122f3e6SDimitry Andric /// need to use the GC API. 436122f3e6SDimitry Andric /// - The destination slot is potentially aliased. 446122f3e6SDimitry Andric bool shouldUseDestForReturnSlot() const { 456122f3e6SDimitry Andric return !(Dest.requiresGCollection() || Dest.isPotentiallyAliased()); 466122f3e6SDimitry Andric } 476122f3e6SDimitry Andric 48f22ef01cSRoman Divacky ReturnValueSlot getReturnValueSlot() const { 496122f3e6SDimitry Andric if (!shouldUseDestForReturnSlot()) 506122f3e6SDimitry Andric return ReturnValueSlot(); 51f22ef01cSRoman Divacky 522754fe60SDimitry Andric return ReturnValueSlot(Dest.getAddr(), Dest.isVolatile()); 532754fe60SDimitry Andric } 542754fe60SDimitry Andric 552754fe60SDimitry Andric AggValueSlot EnsureSlot(QualType T) { 562754fe60SDimitry Andric if (!Dest.isIgnored()) return Dest; 572754fe60SDimitry Andric return CGF.CreateAggTemp(T, "agg.tmp.ensured"); 58f22ef01cSRoman Divacky } 59f22ef01cSRoman Divacky 60f22ef01cSRoman Divacky public: 612754fe60SDimitry Andric AggExprEmitter(CodeGenFunction &cgf, AggValueSlot Dest, 622754fe60SDimitry Andric bool ignore) 632754fe60SDimitry Andric : CGF(cgf), Builder(CGF.Builder), Dest(Dest), 642754fe60SDimitry Andric IgnoreResult(ignore) { 65f22ef01cSRoman Divacky } 66f22ef01cSRoman Divacky 67f22ef01cSRoman Divacky //===--------------------------------------------------------------------===// 68f22ef01cSRoman Divacky // Utilities 69f22ef01cSRoman Divacky //===--------------------------------------------------------------------===// 70f22ef01cSRoman Divacky 71f22ef01cSRoman Divacky /// EmitAggLoadOfLValue - Given an expression with aggregate type that 72f22ef01cSRoman Divacky /// represents a value lvalue, this method emits the address of the lvalue, 73f22ef01cSRoman Divacky /// then loads the result into DestPtr. 74f22ef01cSRoman Divacky void EmitAggLoadOfLValue(const Expr *E); 75f22ef01cSRoman Divacky 76f22ef01cSRoman Divacky /// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. 77f22ef01cSRoman Divacky void EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore = false); 78dff0c46cSDimitry Andric void EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore = false, 79dff0c46cSDimitry Andric unsigned Alignment = 0); 80f22ef01cSRoman Divacky 816122f3e6SDimitry Andric void EmitMoveFromReturnSlot(const Expr *E, RValue Src); 826122f3e6SDimitry Andric 83dff0c46cSDimitry Andric void EmitStdInitializerList(llvm::Value *DestPtr, InitListExpr *InitList); 84dff0c46cSDimitry Andric void EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType, 85dff0c46cSDimitry Andric QualType elementType, InitListExpr *E); 86dff0c46cSDimitry Andric 876122f3e6SDimitry Andric AggValueSlot::NeedsGCBarriers_t needsGC(QualType T) { 88dff0c46cSDimitry Andric if (CGF.getLangOpts().getGC() && TypeRequiresGCollection(T)) 896122f3e6SDimitry Andric return AggValueSlot::NeedsGCBarriers; 906122f3e6SDimitry Andric return AggValueSlot::DoesNotNeedGCBarriers; 916122f3e6SDimitry Andric } 92f22ef01cSRoman Divacky 93f22ef01cSRoman Divacky bool TypeRequiresGCollection(QualType T); 94f22ef01cSRoman Divacky 95f22ef01cSRoman Divacky //===--------------------------------------------------------------------===// 96f22ef01cSRoman Divacky // Visitor Methods 97f22ef01cSRoman Divacky //===--------------------------------------------------------------------===// 98f22ef01cSRoman Divacky 99f22ef01cSRoman Divacky void VisitStmt(Stmt *S) { 100f22ef01cSRoman Divacky CGF.ErrorUnsupported(S, "aggregate expression"); 101f22ef01cSRoman Divacky } 102f22ef01cSRoman Divacky void VisitParenExpr(ParenExpr *PE) { Visit(PE->getSubExpr()); } 1033b0f4066SDimitry Andric void VisitGenericSelectionExpr(GenericSelectionExpr *GE) { 1043b0f4066SDimitry Andric Visit(GE->getResultExpr()); 1053b0f4066SDimitry Andric } 106f22ef01cSRoman Divacky void VisitUnaryExtension(UnaryOperator *E) { Visit(E->getSubExpr()); } 10717a519f9SDimitry Andric void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) { 10817a519f9SDimitry Andric return Visit(E->getReplacement()); 10917a519f9SDimitry Andric } 110f22ef01cSRoman Divacky 111f22ef01cSRoman Divacky // l-values. 112dff0c46cSDimitry Andric void VisitDeclRefExpr(DeclRefExpr *E) { 113dff0c46cSDimitry Andric // For aggregates, we should always be able to emit the variable 114dff0c46cSDimitry Andric // as an l-value unless it's a reference. This is due to the fact 115dff0c46cSDimitry Andric // that we can't actually ever see a normal l2r conversion on an 116dff0c46cSDimitry Andric // aggregate in C++, and in C there's no language standard 117dff0c46cSDimitry Andric // actively preventing us from listing variables in the captures 118dff0c46cSDimitry Andric // list of a block. 119dff0c46cSDimitry Andric if (E->getDecl()->getType()->isReferenceType()) { 120dff0c46cSDimitry Andric if (CodeGenFunction::ConstantEmission result 121dff0c46cSDimitry Andric = CGF.tryEmitAsConstant(E)) { 122dff0c46cSDimitry Andric EmitFinalDestCopy(E, result.getReferenceLValue(CGF, E)); 123dff0c46cSDimitry Andric return; 124dff0c46cSDimitry Andric } 125dff0c46cSDimitry Andric } 126dff0c46cSDimitry Andric 127dff0c46cSDimitry Andric EmitAggLoadOfLValue(E); 128dff0c46cSDimitry Andric } 129dff0c46cSDimitry Andric 130f22ef01cSRoman Divacky void VisitMemberExpr(MemberExpr *ME) { EmitAggLoadOfLValue(ME); } 131f22ef01cSRoman Divacky void VisitUnaryDeref(UnaryOperator *E) { EmitAggLoadOfLValue(E); } 132f22ef01cSRoman Divacky void VisitStringLiteral(StringLiteral *E) { EmitAggLoadOfLValue(E); } 13317a519f9SDimitry Andric void VisitCompoundLiteralExpr(CompoundLiteralExpr *E); 134f22ef01cSRoman Divacky void VisitArraySubscriptExpr(ArraySubscriptExpr *E) { 135f22ef01cSRoman Divacky EmitAggLoadOfLValue(E); 136f22ef01cSRoman Divacky } 137f22ef01cSRoman Divacky void VisitPredefinedExpr(const PredefinedExpr *E) { 138f22ef01cSRoman Divacky EmitAggLoadOfLValue(E); 139f22ef01cSRoman Divacky } 140f22ef01cSRoman Divacky 141f22ef01cSRoman Divacky // Operators. 142f22ef01cSRoman Divacky void VisitCastExpr(CastExpr *E); 143f22ef01cSRoman Divacky void VisitCallExpr(const CallExpr *E); 144f22ef01cSRoman Divacky void VisitStmtExpr(const StmtExpr *E); 145f22ef01cSRoman Divacky void VisitBinaryOperator(const BinaryOperator *BO); 146f22ef01cSRoman Divacky void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *BO); 147f22ef01cSRoman Divacky void VisitBinAssign(const BinaryOperator *E); 148f22ef01cSRoman Divacky void VisitBinComma(const BinaryOperator *E); 149f22ef01cSRoman Divacky 150f22ef01cSRoman Divacky void VisitObjCMessageExpr(ObjCMessageExpr *E); 151f22ef01cSRoman Divacky void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { 152f22ef01cSRoman Divacky EmitAggLoadOfLValue(E); 153f22ef01cSRoman Divacky } 154f22ef01cSRoman Divacky 1552754fe60SDimitry Andric void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO); 156f22ef01cSRoman Divacky void VisitChooseExpr(const ChooseExpr *CE); 157f22ef01cSRoman Divacky void VisitInitListExpr(InitListExpr *E); 158f22ef01cSRoman Divacky void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); 159f22ef01cSRoman Divacky void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { 160f22ef01cSRoman Divacky Visit(DAE->getExpr()); 161f22ef01cSRoman Divacky } 162f22ef01cSRoman Divacky void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); 163f22ef01cSRoman Divacky void VisitCXXConstructExpr(const CXXConstructExpr *E); 164dff0c46cSDimitry Andric void VisitLambdaExpr(LambdaExpr *E); 1652754fe60SDimitry Andric void VisitExprWithCleanups(ExprWithCleanups *E); 166ffd1746dSEd Schouten void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); 167f22ef01cSRoman Divacky void VisitCXXTypeidExpr(CXXTypeidExpr *E) { EmitAggLoadOfLValue(E); } 16817a519f9SDimitry Andric void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); 1692754fe60SDimitry Andric void VisitOpaqueValueExpr(OpaqueValueExpr *E); 1702754fe60SDimitry Andric 171dff0c46cSDimitry Andric void VisitPseudoObjectExpr(PseudoObjectExpr *E) { 172dff0c46cSDimitry Andric if (E->isGLValue()) { 173dff0c46cSDimitry Andric LValue LV = CGF.EmitPseudoObjectLValue(E); 174dff0c46cSDimitry Andric return EmitFinalDestCopy(E, LV); 175dff0c46cSDimitry Andric } 176dff0c46cSDimitry Andric 177dff0c46cSDimitry Andric CGF.EmitPseudoObjectRValue(E, EnsureSlot(E->getType())); 178dff0c46cSDimitry Andric } 179dff0c46cSDimitry Andric 180f22ef01cSRoman Divacky void VisitVAArgExpr(VAArgExpr *E); 181f22ef01cSRoman Divacky 18217a519f9SDimitry Andric void EmitInitializationToLValue(Expr *E, LValue Address); 18317a519f9SDimitry Andric void EmitNullInitializationToLValue(LValue Address); 184f22ef01cSRoman Divacky // case Expr::ChooseExprClass: 185f22ef01cSRoman Divacky void VisitCXXThrowExpr(const CXXThrowExpr *E) { CGF.EmitCXXThrowExpr(E); } 1866122f3e6SDimitry Andric void VisitAtomicExpr(AtomicExpr *E) { 1876122f3e6SDimitry Andric CGF.EmitAtomicExpr(E, EnsureSlot(E->getType()).getAddr()); 1886122f3e6SDimitry Andric } 189f22ef01cSRoman Divacky }; 190f22ef01cSRoman Divacky } // end anonymous namespace. 191f22ef01cSRoman Divacky 192f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 193f22ef01cSRoman Divacky // Utilities 194f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 195f22ef01cSRoman Divacky 196f22ef01cSRoman Divacky /// EmitAggLoadOfLValue - Given an expression with aggregate type that 197f22ef01cSRoman Divacky /// represents a value lvalue, this method emits the address of the lvalue, 198f22ef01cSRoman Divacky /// then loads the result into DestPtr. 199f22ef01cSRoman Divacky void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) { 200f22ef01cSRoman Divacky LValue LV = CGF.EmitLValue(E); 201f22ef01cSRoman Divacky EmitFinalDestCopy(E, LV); 202f22ef01cSRoman Divacky } 203f22ef01cSRoman Divacky 204f22ef01cSRoman Divacky /// \brief True if the given aggregate type requires special GC API calls. 205f22ef01cSRoman Divacky bool AggExprEmitter::TypeRequiresGCollection(QualType T) { 206f22ef01cSRoman Divacky // Only record types have members that might require garbage collection. 207f22ef01cSRoman Divacky const RecordType *RecordTy = T->getAs<RecordType>(); 208f22ef01cSRoman Divacky if (!RecordTy) return false; 209f22ef01cSRoman Divacky 210f22ef01cSRoman Divacky // Don't mess with non-trivial C++ types. 211f22ef01cSRoman Divacky RecordDecl *Record = RecordTy->getDecl(); 212f22ef01cSRoman Divacky if (isa<CXXRecordDecl>(Record) && 213f22ef01cSRoman Divacky (!cast<CXXRecordDecl>(Record)->hasTrivialCopyConstructor() || 214f22ef01cSRoman Divacky !cast<CXXRecordDecl>(Record)->hasTrivialDestructor())) 215f22ef01cSRoman Divacky return false; 216f22ef01cSRoman Divacky 217f22ef01cSRoman Divacky // Check whether the type has an object member. 218f22ef01cSRoman Divacky return Record->hasObjectMember(); 219f22ef01cSRoman Divacky } 220f22ef01cSRoman Divacky 2216122f3e6SDimitry Andric /// \brief Perform the final move to DestPtr if for some reason 2226122f3e6SDimitry Andric /// getReturnValueSlot() didn't use it directly. 223f22ef01cSRoman Divacky /// 224f22ef01cSRoman Divacky /// The idea is that you do something like this: 225f22ef01cSRoman Divacky /// RValue Result = EmitSomething(..., getReturnValueSlot()); 2266122f3e6SDimitry Andric /// EmitMoveFromReturnSlot(E, Result); 2276122f3e6SDimitry Andric /// 2286122f3e6SDimitry Andric /// If nothing interferes, this will cause the result to be emitted 2296122f3e6SDimitry Andric /// directly into the return value slot. Otherwise, a final move 2306122f3e6SDimitry Andric /// will be performed. 2316122f3e6SDimitry Andric void AggExprEmitter::EmitMoveFromReturnSlot(const Expr *E, RValue Src) { 2326122f3e6SDimitry Andric if (shouldUseDestForReturnSlot()) { 2336122f3e6SDimitry Andric // Logically, Dest.getAddr() should equal Src.getAggregateAddr(). 2346122f3e6SDimitry Andric // The possibility of undef rvalues complicates that a lot, 2356122f3e6SDimitry Andric // though, so we can't really assert. 2366122f3e6SDimitry Andric return; 237ffd1746dSEd Schouten } 2386122f3e6SDimitry Andric 2396122f3e6SDimitry Andric // Otherwise, do a final copy, 2406122f3e6SDimitry Andric assert(Dest.getAddr() != Src.getAggregateAddr()); 241cb4dff85SDimitry Andric std::pair<CharUnits, CharUnits> TypeInfo = 242cb4dff85SDimitry Andric CGF.getContext().getTypeInfoInChars(E->getType()); 243cb4dff85SDimitry Andric CharUnits Alignment = std::min(TypeInfo.second, Dest.getAlignment()); 244cb4dff85SDimitry Andric EmitFinalDestCopy(E, Src, /*Ignore*/ true, Alignment.getQuantity()); 245f22ef01cSRoman Divacky } 246f22ef01cSRoman Divacky 247f22ef01cSRoman Divacky /// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. 248dff0c46cSDimitry Andric void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore, 249dff0c46cSDimitry Andric unsigned Alignment) { 250f22ef01cSRoman Divacky assert(Src.isAggregate() && "value must be aggregate value!"); 251f22ef01cSRoman Divacky 2522754fe60SDimitry Andric // If Dest is ignored, then we're evaluating an aggregate expression 253e580952dSDimitry Andric // in a context (like an expression statement) that doesn't care 254e580952dSDimitry Andric // about the result. C says that an lvalue-to-rvalue conversion is 255e580952dSDimitry Andric // performed in these cases; C++ says that it is not. In either 256e580952dSDimitry Andric // case, we don't actually need to do anything unless the value is 257e580952dSDimitry Andric // volatile. 2582754fe60SDimitry Andric if (Dest.isIgnored()) { 259e580952dSDimitry Andric if (!Src.isVolatileQualified() || 260dff0c46cSDimitry Andric CGF.CGM.getLangOpts().CPlusPlus || 261e580952dSDimitry Andric (IgnoreResult && Ignore)) 262f22ef01cSRoman Divacky return; 263e580952dSDimitry Andric 264f22ef01cSRoman Divacky // If the source is volatile, we must read from it; to do that, we need 265f22ef01cSRoman Divacky // some place to put it. 2662754fe60SDimitry Andric Dest = CGF.CreateAggTemp(E->getType(), "agg.tmp"); 267f22ef01cSRoman Divacky } 268f22ef01cSRoman Divacky 2692754fe60SDimitry Andric if (Dest.requiresGCollection()) { 2703b0f4066SDimitry Andric CharUnits size = CGF.getContext().getTypeSizeInChars(E->getType()); 2716122f3e6SDimitry Andric llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); 2723b0f4066SDimitry Andric llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size.getQuantity()); 273f22ef01cSRoman Divacky CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, 2742754fe60SDimitry Andric Dest.getAddr(), 2752754fe60SDimitry Andric Src.getAggregateAddr(), 276ffd1746dSEd Schouten SizeVal); 277f22ef01cSRoman Divacky return; 278f22ef01cSRoman Divacky } 279f22ef01cSRoman Divacky // If the result of the assignment is used, copy the LHS there also. 280f22ef01cSRoman Divacky // FIXME: Pass VolatileDest as well. I think we also need to merge volatile 281f22ef01cSRoman Divacky // from the source as well, as we can't eliminate it if either operand 282f22ef01cSRoman Divacky // is volatile, unless copy has volatile for both source and destination.. 2832754fe60SDimitry Andric CGF.EmitAggregateCopy(Dest.getAddr(), Src.getAggregateAddr(), E->getType(), 284dff0c46cSDimitry Andric Dest.isVolatile()|Src.isVolatileQualified(), 285dff0c46cSDimitry Andric Alignment); 286f22ef01cSRoman Divacky } 287f22ef01cSRoman Divacky 288f22ef01cSRoman Divacky /// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. 289f22ef01cSRoman Divacky void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) { 290f22ef01cSRoman Divacky assert(Src.isSimple() && "Can't have aggregate bitfield, vector, etc"); 291f22ef01cSRoman Divacky 292dff0c46cSDimitry Andric CharUnits Alignment = std::min(Src.getAlignment(), Dest.getAlignment()); 293dff0c46cSDimitry Andric EmitFinalDestCopy(E, Src.asAggregateRValue(), Ignore, Alignment.getQuantity()); 294dff0c46cSDimitry Andric } 295dff0c46cSDimitry Andric 296dff0c46cSDimitry Andric static QualType GetStdInitializerListElementType(QualType T) { 297dff0c46cSDimitry Andric // Just assume that this is really std::initializer_list. 298dff0c46cSDimitry Andric ClassTemplateSpecializationDecl *specialization = 299dff0c46cSDimitry Andric cast<ClassTemplateSpecializationDecl>(T->castAs<RecordType>()->getDecl()); 300dff0c46cSDimitry Andric return specialization->getTemplateArgs()[0].getAsType(); 301dff0c46cSDimitry Andric } 302dff0c46cSDimitry Andric 303dff0c46cSDimitry Andric /// \brief Prepare cleanup for the temporary array. 304dff0c46cSDimitry Andric static void EmitStdInitializerListCleanup(CodeGenFunction &CGF, 305dff0c46cSDimitry Andric QualType arrayType, 306dff0c46cSDimitry Andric llvm::Value *addr, 307dff0c46cSDimitry Andric const InitListExpr *initList) { 308dff0c46cSDimitry Andric QualType::DestructionKind dtorKind = arrayType.isDestructedType(); 309dff0c46cSDimitry Andric if (!dtorKind) 310dff0c46cSDimitry Andric return; // Type doesn't need destroying. 311dff0c46cSDimitry Andric if (dtorKind != QualType::DK_cxx_destructor) { 312dff0c46cSDimitry Andric CGF.ErrorUnsupported(initList, "ObjC ARC type in initializer_list"); 313dff0c46cSDimitry Andric return; 314dff0c46cSDimitry Andric } 315dff0c46cSDimitry Andric 316dff0c46cSDimitry Andric CodeGenFunction::Destroyer *destroyer = CGF.getDestroyer(dtorKind); 317dff0c46cSDimitry Andric CGF.pushDestroy(NormalAndEHCleanup, addr, arrayType, destroyer, 318dff0c46cSDimitry Andric /*EHCleanup=*/true); 319dff0c46cSDimitry Andric } 320dff0c46cSDimitry Andric 321dff0c46cSDimitry Andric /// \brief Emit the initializer for a std::initializer_list initialized with a 322dff0c46cSDimitry Andric /// real initializer list. 323dff0c46cSDimitry Andric void AggExprEmitter::EmitStdInitializerList(llvm::Value *destPtr, 324dff0c46cSDimitry Andric InitListExpr *initList) { 325dff0c46cSDimitry Andric // We emit an array containing the elements, then have the init list point 326dff0c46cSDimitry Andric // at the array. 327dff0c46cSDimitry Andric ASTContext &ctx = CGF.getContext(); 328dff0c46cSDimitry Andric unsigned numInits = initList->getNumInits(); 329dff0c46cSDimitry Andric QualType element = GetStdInitializerListElementType(initList->getType()); 330dff0c46cSDimitry Andric llvm::APInt size(ctx.getTypeSize(ctx.getSizeType()), numInits); 331dff0c46cSDimitry Andric QualType array = ctx.getConstantArrayType(element, size, ArrayType::Normal,0); 332dff0c46cSDimitry Andric llvm::Type *LTy = CGF.ConvertTypeForMem(array); 333dff0c46cSDimitry Andric llvm::AllocaInst *alloc = CGF.CreateTempAlloca(LTy); 334dff0c46cSDimitry Andric alloc->setAlignment(ctx.getTypeAlignInChars(array).getQuantity()); 335dff0c46cSDimitry Andric alloc->setName(".initlist."); 336dff0c46cSDimitry Andric 337dff0c46cSDimitry Andric EmitArrayInit(alloc, cast<llvm::ArrayType>(LTy), element, initList); 338dff0c46cSDimitry Andric 339dff0c46cSDimitry Andric // FIXME: The diagnostics are somewhat out of place here. 340dff0c46cSDimitry Andric RecordDecl *record = initList->getType()->castAs<RecordType>()->getDecl(); 341dff0c46cSDimitry Andric RecordDecl::field_iterator field = record->field_begin(); 342dff0c46cSDimitry Andric if (field == record->field_end()) { 343dff0c46cSDimitry Andric CGF.ErrorUnsupported(initList, "weird std::initializer_list"); 344dff0c46cSDimitry Andric return; 345dff0c46cSDimitry Andric } 346dff0c46cSDimitry Andric 347dff0c46cSDimitry Andric QualType elementPtr = ctx.getPointerType(element.withConst()); 348dff0c46cSDimitry Andric 349dff0c46cSDimitry Andric // Start pointer. 350dff0c46cSDimitry Andric if (!ctx.hasSameType(field->getType(), elementPtr)) { 351dff0c46cSDimitry Andric CGF.ErrorUnsupported(initList, "weird std::initializer_list"); 352dff0c46cSDimitry Andric return; 353dff0c46cSDimitry Andric } 354cb4dff85SDimitry Andric LValue DestLV = CGF.MakeNaturalAlignAddrLValue(destPtr, initList->getType()); 355cb4dff85SDimitry Andric LValue start = CGF.EmitLValueForFieldInitialization(DestLV, *field); 356dff0c46cSDimitry Andric llvm::Value *arrayStart = Builder.CreateStructGEP(alloc, 0, "arraystart"); 357dff0c46cSDimitry Andric CGF.EmitStoreThroughLValue(RValue::get(arrayStart), start); 358dff0c46cSDimitry Andric ++field; 359dff0c46cSDimitry Andric 360dff0c46cSDimitry Andric if (field == record->field_end()) { 361dff0c46cSDimitry Andric CGF.ErrorUnsupported(initList, "weird std::initializer_list"); 362dff0c46cSDimitry Andric return; 363dff0c46cSDimitry Andric } 364cb4dff85SDimitry Andric LValue endOrLength = CGF.EmitLValueForFieldInitialization(DestLV, *field); 365dff0c46cSDimitry Andric if (ctx.hasSameType(field->getType(), elementPtr)) { 366dff0c46cSDimitry Andric // End pointer. 367dff0c46cSDimitry Andric llvm::Value *arrayEnd = Builder.CreateStructGEP(alloc,numInits, "arrayend"); 368dff0c46cSDimitry Andric CGF.EmitStoreThroughLValue(RValue::get(arrayEnd), endOrLength); 369dff0c46cSDimitry Andric } else if(ctx.hasSameType(field->getType(), ctx.getSizeType())) { 370dff0c46cSDimitry Andric // Length. 371dff0c46cSDimitry Andric CGF.EmitStoreThroughLValue(RValue::get(Builder.getInt(size)), endOrLength); 372dff0c46cSDimitry Andric } else { 373dff0c46cSDimitry Andric CGF.ErrorUnsupported(initList, "weird std::initializer_list"); 374dff0c46cSDimitry Andric return; 375dff0c46cSDimitry Andric } 376dff0c46cSDimitry Andric 377dff0c46cSDimitry Andric if (!Dest.isExternallyDestructed()) 378dff0c46cSDimitry Andric EmitStdInitializerListCleanup(CGF, array, alloc, initList); 379dff0c46cSDimitry Andric } 380dff0c46cSDimitry Andric 381dff0c46cSDimitry Andric /// \brief Emit initialization of an array from an initializer list. 382dff0c46cSDimitry Andric void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType, 383dff0c46cSDimitry Andric QualType elementType, InitListExpr *E) { 384dff0c46cSDimitry Andric uint64_t NumInitElements = E->getNumInits(); 385dff0c46cSDimitry Andric 386dff0c46cSDimitry Andric uint64_t NumArrayElements = AType->getNumElements(); 387dff0c46cSDimitry Andric assert(NumInitElements <= NumArrayElements); 388dff0c46cSDimitry Andric 389dff0c46cSDimitry Andric // DestPtr is an array*. Construct an elementType* by drilling 390dff0c46cSDimitry Andric // down a level. 391dff0c46cSDimitry Andric llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); 392dff0c46cSDimitry Andric llvm::Value *indices[] = { zero, zero }; 393dff0c46cSDimitry Andric llvm::Value *begin = 394dff0c46cSDimitry Andric Builder.CreateInBoundsGEP(DestPtr, indices, "arrayinit.begin"); 395dff0c46cSDimitry Andric 396dff0c46cSDimitry Andric // Exception safety requires us to destroy all the 397dff0c46cSDimitry Andric // already-constructed members if an initializer throws. 398dff0c46cSDimitry Andric // For that, we'll need an EH cleanup. 399dff0c46cSDimitry Andric QualType::DestructionKind dtorKind = elementType.isDestructedType(); 400dff0c46cSDimitry Andric llvm::AllocaInst *endOfInit = 0; 401dff0c46cSDimitry Andric EHScopeStack::stable_iterator cleanup; 402dff0c46cSDimitry Andric llvm::Instruction *cleanupDominator = 0; 403dff0c46cSDimitry Andric if (CGF.needsEHCleanup(dtorKind)) { 404dff0c46cSDimitry Andric // In principle we could tell the cleanup where we are more 405dff0c46cSDimitry Andric // directly, but the control flow can get so varied here that it 406dff0c46cSDimitry Andric // would actually be quite complex. Therefore we go through an 407dff0c46cSDimitry Andric // alloca. 408dff0c46cSDimitry Andric endOfInit = CGF.CreateTempAlloca(begin->getType(), 409dff0c46cSDimitry Andric "arrayinit.endOfInit"); 410dff0c46cSDimitry Andric cleanupDominator = Builder.CreateStore(begin, endOfInit); 411dff0c46cSDimitry Andric CGF.pushIrregularPartialArrayCleanup(begin, endOfInit, elementType, 412dff0c46cSDimitry Andric CGF.getDestroyer(dtorKind)); 413dff0c46cSDimitry Andric cleanup = CGF.EHStack.stable_begin(); 414dff0c46cSDimitry Andric 415dff0c46cSDimitry Andric // Otherwise, remember that we didn't need a cleanup. 416dff0c46cSDimitry Andric } else { 417dff0c46cSDimitry Andric dtorKind = QualType::DK_none; 418dff0c46cSDimitry Andric } 419dff0c46cSDimitry Andric 420dff0c46cSDimitry Andric llvm::Value *one = llvm::ConstantInt::get(CGF.SizeTy, 1); 421dff0c46cSDimitry Andric 422dff0c46cSDimitry Andric // The 'current element to initialize'. The invariants on this 423dff0c46cSDimitry Andric // variable are complicated. Essentially, after each iteration of 424dff0c46cSDimitry Andric // the loop, it points to the last initialized element, except 425dff0c46cSDimitry Andric // that it points to the beginning of the array before any 426dff0c46cSDimitry Andric // elements have been initialized. 427dff0c46cSDimitry Andric llvm::Value *element = begin; 428dff0c46cSDimitry Andric 429dff0c46cSDimitry Andric // Emit the explicit initializers. 430dff0c46cSDimitry Andric for (uint64_t i = 0; i != NumInitElements; ++i) { 431dff0c46cSDimitry Andric // Advance to the next element. 432dff0c46cSDimitry Andric if (i > 0) { 433dff0c46cSDimitry Andric element = Builder.CreateInBoundsGEP(element, one, "arrayinit.element"); 434dff0c46cSDimitry Andric 435dff0c46cSDimitry Andric // Tell the cleanup that it needs to destroy up to this 436dff0c46cSDimitry Andric // element. TODO: some of these stores can be trivially 437dff0c46cSDimitry Andric // observed to be unnecessary. 438dff0c46cSDimitry Andric if (endOfInit) Builder.CreateStore(element, endOfInit); 439dff0c46cSDimitry Andric } 440dff0c46cSDimitry Andric 441dff0c46cSDimitry Andric // If these are nested std::initializer_list inits, do them directly, 442dff0c46cSDimitry Andric // because they are conceptually the same "location". 443dff0c46cSDimitry Andric InitListExpr *initList = dyn_cast<InitListExpr>(E->getInit(i)); 444dff0c46cSDimitry Andric if (initList && initList->initializesStdInitializerList()) { 445dff0c46cSDimitry Andric EmitStdInitializerList(element, initList); 446dff0c46cSDimitry Andric } else { 447dff0c46cSDimitry Andric LValue elementLV = CGF.MakeAddrLValue(element, elementType); 448dff0c46cSDimitry Andric EmitInitializationToLValue(E->getInit(i), elementLV); 449dff0c46cSDimitry Andric } 450dff0c46cSDimitry Andric } 451dff0c46cSDimitry Andric 452dff0c46cSDimitry Andric // Check whether there's a non-trivial array-fill expression. 453dff0c46cSDimitry Andric // Note that this will be a CXXConstructExpr even if the element 454dff0c46cSDimitry Andric // type is an array (or array of array, etc.) of class type. 455dff0c46cSDimitry Andric Expr *filler = E->getArrayFiller(); 456dff0c46cSDimitry Andric bool hasTrivialFiller = true; 457dff0c46cSDimitry Andric if (CXXConstructExpr *cons = dyn_cast_or_null<CXXConstructExpr>(filler)) { 458dff0c46cSDimitry Andric assert(cons->getConstructor()->isDefaultConstructor()); 459dff0c46cSDimitry Andric hasTrivialFiller = cons->getConstructor()->isTrivial(); 460dff0c46cSDimitry Andric } 461dff0c46cSDimitry Andric 462dff0c46cSDimitry Andric // Any remaining elements need to be zero-initialized, possibly 463dff0c46cSDimitry Andric // using the filler expression. We can skip this if the we're 464dff0c46cSDimitry Andric // emitting to zeroed memory. 465dff0c46cSDimitry Andric if (NumInitElements != NumArrayElements && 466dff0c46cSDimitry Andric !(Dest.isZeroed() && hasTrivialFiller && 467dff0c46cSDimitry Andric CGF.getTypes().isZeroInitializable(elementType))) { 468dff0c46cSDimitry Andric 469dff0c46cSDimitry Andric // Use an actual loop. This is basically 470dff0c46cSDimitry Andric // do { *array++ = filler; } while (array != end); 471dff0c46cSDimitry Andric 472dff0c46cSDimitry Andric // Advance to the start of the rest of the array. 473dff0c46cSDimitry Andric if (NumInitElements) { 474dff0c46cSDimitry Andric element = Builder.CreateInBoundsGEP(element, one, "arrayinit.start"); 475dff0c46cSDimitry Andric if (endOfInit) Builder.CreateStore(element, endOfInit); 476dff0c46cSDimitry Andric } 477dff0c46cSDimitry Andric 478dff0c46cSDimitry Andric // Compute the end of the array. 479dff0c46cSDimitry Andric llvm::Value *end = Builder.CreateInBoundsGEP(begin, 480dff0c46cSDimitry Andric llvm::ConstantInt::get(CGF.SizeTy, NumArrayElements), 481dff0c46cSDimitry Andric "arrayinit.end"); 482dff0c46cSDimitry Andric 483dff0c46cSDimitry Andric llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); 484dff0c46cSDimitry Andric llvm::BasicBlock *bodyBB = CGF.createBasicBlock("arrayinit.body"); 485dff0c46cSDimitry Andric 486dff0c46cSDimitry Andric // Jump into the body. 487dff0c46cSDimitry Andric CGF.EmitBlock(bodyBB); 488dff0c46cSDimitry Andric llvm::PHINode *currentElement = 489dff0c46cSDimitry Andric Builder.CreatePHI(element->getType(), 2, "arrayinit.cur"); 490dff0c46cSDimitry Andric currentElement->addIncoming(element, entryBB); 491dff0c46cSDimitry Andric 492dff0c46cSDimitry Andric // Emit the actual filler expression. 493dff0c46cSDimitry Andric LValue elementLV = CGF.MakeAddrLValue(currentElement, elementType); 494dff0c46cSDimitry Andric if (filler) 495dff0c46cSDimitry Andric EmitInitializationToLValue(filler, elementLV); 496dff0c46cSDimitry Andric else 497dff0c46cSDimitry Andric EmitNullInitializationToLValue(elementLV); 498dff0c46cSDimitry Andric 499dff0c46cSDimitry Andric // Move on to the next element. 500dff0c46cSDimitry Andric llvm::Value *nextElement = 501dff0c46cSDimitry Andric Builder.CreateInBoundsGEP(currentElement, one, "arrayinit.next"); 502dff0c46cSDimitry Andric 503dff0c46cSDimitry Andric // Tell the EH cleanup that we finished with the last element. 504dff0c46cSDimitry Andric if (endOfInit) Builder.CreateStore(nextElement, endOfInit); 505dff0c46cSDimitry Andric 506dff0c46cSDimitry Andric // Leave the loop if we're done. 507dff0c46cSDimitry Andric llvm::Value *done = Builder.CreateICmpEQ(nextElement, end, 508dff0c46cSDimitry Andric "arrayinit.done"); 509dff0c46cSDimitry Andric llvm::BasicBlock *endBB = CGF.createBasicBlock("arrayinit.end"); 510dff0c46cSDimitry Andric Builder.CreateCondBr(done, endBB, bodyBB); 511dff0c46cSDimitry Andric currentElement->addIncoming(nextElement, Builder.GetInsertBlock()); 512dff0c46cSDimitry Andric 513dff0c46cSDimitry Andric CGF.EmitBlock(endBB); 514dff0c46cSDimitry Andric } 515dff0c46cSDimitry Andric 516dff0c46cSDimitry Andric // Leave the partial-array cleanup if we entered one. 517dff0c46cSDimitry Andric if (dtorKind) CGF.DeactivateCleanupBlock(cleanup, cleanupDominator); 518f22ef01cSRoman Divacky } 519f22ef01cSRoman Divacky 520f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 521f22ef01cSRoman Divacky // Visitor Methods 522f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 523f22ef01cSRoman Divacky 52417a519f9SDimitry Andric void AggExprEmitter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E){ 52517a519f9SDimitry Andric Visit(E->GetTemporaryExpr()); 52617a519f9SDimitry Andric } 52717a519f9SDimitry Andric 5282754fe60SDimitry Andric void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) { 5292754fe60SDimitry Andric EmitFinalDestCopy(e, CGF.getOpaqueLValueMapping(e)); 5302754fe60SDimitry Andric } 5312754fe60SDimitry Andric 53217a519f9SDimitry Andric void 53317a519f9SDimitry Andric AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { 53417a519f9SDimitry Andric if (E->getType().isPODType(CGF.getContext())) { 53517a519f9SDimitry Andric // For a POD type, just emit a load of the lvalue + a copy, because our 53617a519f9SDimitry Andric // compound literal might alias the destination. 53717a519f9SDimitry Andric // FIXME: This is a band-aid; the real problem appears to be in our handling 53817a519f9SDimitry Andric // of assignments, where we store directly into the LHS without checking 53917a519f9SDimitry Andric // whether anything in the RHS aliases. 54017a519f9SDimitry Andric EmitAggLoadOfLValue(E); 54117a519f9SDimitry Andric return; 54217a519f9SDimitry Andric } 54317a519f9SDimitry Andric 54417a519f9SDimitry Andric AggValueSlot Slot = EnsureSlot(E->getType()); 54517a519f9SDimitry Andric CGF.EmitAggExpr(E->getInitializer(), Slot); 54617a519f9SDimitry Andric } 54717a519f9SDimitry Andric 54817a519f9SDimitry Andric 549f22ef01cSRoman Divacky void AggExprEmitter::VisitCastExpr(CastExpr *E) { 550f22ef01cSRoman Divacky switch (E->getCastKind()) { 551e580952dSDimitry Andric case CK_Dynamic: { 552f22ef01cSRoman Divacky assert(isa<CXXDynamicCastExpr>(E) && "CK_Dynamic without a dynamic_cast?"); 553f22ef01cSRoman Divacky LValue LV = CGF.EmitCheckedLValue(E->getSubExpr()); 554f22ef01cSRoman Divacky // FIXME: Do we also need to handle property references here? 555f22ef01cSRoman Divacky if (LV.isSimple()) 556f22ef01cSRoman Divacky CGF.EmitDynamicCast(LV.getAddress(), cast<CXXDynamicCastExpr>(E)); 557f22ef01cSRoman Divacky else 558f22ef01cSRoman Divacky CGF.CGM.ErrorUnsupported(E, "non-simple lvalue dynamic_cast"); 559f22ef01cSRoman Divacky 5602754fe60SDimitry Andric if (!Dest.isIgnored()) 561f22ef01cSRoman Divacky CGF.CGM.ErrorUnsupported(E, "lvalue dynamic_cast with a destination"); 562f22ef01cSRoman Divacky break; 563f22ef01cSRoman Divacky } 564f22ef01cSRoman Divacky 565e580952dSDimitry Andric case CK_ToUnion: { 5663b0f4066SDimitry Andric if (Dest.isIgnored()) break; 5673b0f4066SDimitry Andric 568f22ef01cSRoman Divacky // GCC union extension 569e580952dSDimitry Andric QualType Ty = E->getSubExpr()->getType(); 570e580952dSDimitry Andric QualType PtrTy = CGF.getContext().getPointerType(Ty); 5712754fe60SDimitry Andric llvm::Value *CastPtr = Builder.CreateBitCast(Dest.getAddr(), 572f22ef01cSRoman Divacky CGF.ConvertType(PtrTy)); 57317a519f9SDimitry Andric EmitInitializationToLValue(E->getSubExpr(), 57417a519f9SDimitry Andric CGF.MakeAddrLValue(CastPtr, Ty)); 575f22ef01cSRoman Divacky break; 576f22ef01cSRoman Divacky } 577f22ef01cSRoman Divacky 578e580952dSDimitry Andric case CK_DerivedToBase: 579e580952dSDimitry Andric case CK_BaseToDerived: 580e580952dSDimitry Andric case CK_UncheckedDerivedToBase: { 5816122f3e6SDimitry Andric llvm_unreachable("cannot perform hierarchy conversion in EmitAggExpr: " 582f22ef01cSRoman Divacky "should have been unpacked before we got here"); 583f22ef01cSRoman Divacky } 584f22ef01cSRoman Divacky 5852754fe60SDimitry Andric case CK_LValueToRValue: // hope for downstream optimization 586e580952dSDimitry Andric case CK_NoOp: 587dff0c46cSDimitry Andric case CK_AtomicToNonAtomic: 588dff0c46cSDimitry Andric case CK_NonAtomicToAtomic: 589e580952dSDimitry Andric case CK_UserDefinedConversion: 590e580952dSDimitry Andric case CK_ConstructorConversion: 591f22ef01cSRoman Divacky assert(CGF.getContext().hasSameUnqualifiedType(E->getSubExpr()->getType(), 592f22ef01cSRoman Divacky E->getType()) && 593f22ef01cSRoman Divacky "Implicit cast types must be compatible"); 594f22ef01cSRoman Divacky Visit(E->getSubExpr()); 595f22ef01cSRoman Divacky break; 596f22ef01cSRoman Divacky 597e580952dSDimitry Andric case CK_LValueBitCast: 5982754fe60SDimitry Andric llvm_unreachable("should not be emitting lvalue bitcast as rvalue"); 5992754fe60SDimitry Andric 6002754fe60SDimitry Andric case CK_Dependent: 6012754fe60SDimitry Andric case CK_BitCast: 6022754fe60SDimitry Andric case CK_ArrayToPointerDecay: 6032754fe60SDimitry Andric case CK_FunctionToPointerDecay: 6042754fe60SDimitry Andric case CK_NullToPointer: 6052754fe60SDimitry Andric case CK_NullToMemberPointer: 6062754fe60SDimitry Andric case CK_BaseToDerivedMemberPointer: 6072754fe60SDimitry Andric case CK_DerivedToBaseMemberPointer: 6082754fe60SDimitry Andric case CK_MemberPointerToBoolean: 609dff0c46cSDimitry Andric case CK_ReinterpretMemberPointer: 6102754fe60SDimitry Andric case CK_IntegralToPointer: 6112754fe60SDimitry Andric case CK_PointerToIntegral: 6122754fe60SDimitry Andric case CK_PointerToBoolean: 6132754fe60SDimitry Andric case CK_ToVoid: 6142754fe60SDimitry Andric case CK_VectorSplat: 6152754fe60SDimitry Andric case CK_IntegralCast: 6162754fe60SDimitry Andric case CK_IntegralToBoolean: 6172754fe60SDimitry Andric case CK_IntegralToFloating: 6182754fe60SDimitry Andric case CK_FloatingToIntegral: 6192754fe60SDimitry Andric case CK_FloatingToBoolean: 6202754fe60SDimitry Andric case CK_FloatingCast: 6216122f3e6SDimitry Andric case CK_CPointerToObjCPointerCast: 6226122f3e6SDimitry Andric case CK_BlockPointerToObjCPointerCast: 6232754fe60SDimitry Andric case CK_AnyPointerToBlockPointerCast: 6242754fe60SDimitry Andric case CK_ObjCObjectLValueCast: 6252754fe60SDimitry Andric case CK_FloatingRealToComplex: 6262754fe60SDimitry Andric case CK_FloatingComplexToReal: 6272754fe60SDimitry Andric case CK_FloatingComplexToBoolean: 6282754fe60SDimitry Andric case CK_FloatingComplexCast: 6292754fe60SDimitry Andric case CK_FloatingComplexToIntegralComplex: 6302754fe60SDimitry Andric case CK_IntegralRealToComplex: 6312754fe60SDimitry Andric case CK_IntegralComplexToReal: 6322754fe60SDimitry Andric case CK_IntegralComplexToBoolean: 6332754fe60SDimitry Andric case CK_IntegralComplexCast: 6342754fe60SDimitry Andric case CK_IntegralComplexToFloatingComplex: 6356122f3e6SDimitry Andric case CK_ARCProduceObject: 6366122f3e6SDimitry Andric case CK_ARCConsumeObject: 6376122f3e6SDimitry Andric case CK_ARCReclaimReturnedObject: 6386122f3e6SDimitry Andric case CK_ARCExtendBlockObject: 639dff0c46cSDimitry Andric case CK_CopyAndAutoreleaseBlockObject: 6402754fe60SDimitry Andric llvm_unreachable("cast kind invalid for aggregate types"); 641f22ef01cSRoman Divacky } 642f22ef01cSRoman Divacky } 643f22ef01cSRoman Divacky 644f22ef01cSRoman Divacky void AggExprEmitter::VisitCallExpr(const CallExpr *E) { 645f22ef01cSRoman Divacky if (E->getCallReturnType()->isReferenceType()) { 646f22ef01cSRoman Divacky EmitAggLoadOfLValue(E); 647f22ef01cSRoman Divacky return; 648f22ef01cSRoman Divacky } 649f22ef01cSRoman Divacky 650f22ef01cSRoman Divacky RValue RV = CGF.EmitCallExpr(E, getReturnValueSlot()); 6516122f3e6SDimitry Andric EmitMoveFromReturnSlot(E, RV); 652f22ef01cSRoman Divacky } 653f22ef01cSRoman Divacky 654f22ef01cSRoman Divacky void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) { 655f22ef01cSRoman Divacky RValue RV = CGF.EmitObjCMessageExpr(E, getReturnValueSlot()); 6566122f3e6SDimitry Andric EmitMoveFromReturnSlot(E, RV); 657f22ef01cSRoman Divacky } 658f22ef01cSRoman Divacky 659f22ef01cSRoman Divacky void AggExprEmitter::VisitBinComma(const BinaryOperator *E) { 6602754fe60SDimitry Andric CGF.EmitIgnoredExpr(E->getLHS()); 6612754fe60SDimitry Andric Visit(E->getRHS()); 662f22ef01cSRoman Divacky } 663f22ef01cSRoman Divacky 664f22ef01cSRoman Divacky void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) { 6652754fe60SDimitry Andric CodeGenFunction::StmtExprEvaluation eval(CGF); 6662754fe60SDimitry Andric CGF.EmitCompoundStmt(*E->getSubStmt(), true, Dest); 667f22ef01cSRoman Divacky } 668f22ef01cSRoman Divacky 669f22ef01cSRoman Divacky void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) { 670e580952dSDimitry Andric if (E->getOpcode() == BO_PtrMemD || E->getOpcode() == BO_PtrMemI) 671f22ef01cSRoman Divacky VisitPointerToDataMemberBinaryOperator(E); 672f22ef01cSRoman Divacky else 673f22ef01cSRoman Divacky CGF.ErrorUnsupported(E, "aggregate binary expression"); 674f22ef01cSRoman Divacky } 675f22ef01cSRoman Divacky 676f22ef01cSRoman Divacky void AggExprEmitter::VisitPointerToDataMemberBinaryOperator( 677f22ef01cSRoman Divacky const BinaryOperator *E) { 678f22ef01cSRoman Divacky LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(E); 679f22ef01cSRoman Divacky EmitFinalDestCopy(E, LV); 680f22ef01cSRoman Divacky } 681f22ef01cSRoman Divacky 682f22ef01cSRoman Divacky void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { 683f22ef01cSRoman Divacky // For an assignment to work, the value on the right has 684f22ef01cSRoman Divacky // to be compatible with the value on the left. 685f22ef01cSRoman Divacky assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(), 686f22ef01cSRoman Divacky E->getRHS()->getType()) 687f22ef01cSRoman Divacky && "Invalid assignment"); 6882754fe60SDimitry Andric 6893b0f4066SDimitry Andric if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->getLHS())) 6903b0f4066SDimitry Andric if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) 6913b0f4066SDimitry Andric if (VD->hasAttr<BlocksAttr>() && 6923b0f4066SDimitry Andric E->getRHS()->HasSideEffects(CGF.getContext())) { 6933b0f4066SDimitry Andric // When __block variable on LHS, the RHS must be evaluated first 6943b0f4066SDimitry Andric // as it may change the 'forwarding' field via call to Block_copy. 6953b0f4066SDimitry Andric LValue RHS = CGF.EmitLValue(E->getRHS()); 6963b0f4066SDimitry Andric LValue LHS = CGF.EmitLValue(E->getLHS()); 6976122f3e6SDimitry Andric Dest = AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed, 6986122f3e6SDimitry Andric needsGC(E->getLHS()->getType()), 6996122f3e6SDimitry Andric AggValueSlot::IsAliased); 7003b0f4066SDimitry Andric EmitFinalDestCopy(E, RHS, true); 7013b0f4066SDimitry Andric return; 7023b0f4066SDimitry Andric } 7033b0f4066SDimitry Andric 704f22ef01cSRoman Divacky LValue LHS = CGF.EmitLValue(E->getLHS()); 705f22ef01cSRoman Divacky 706f22ef01cSRoman Divacky // Codegen the RHS so that it stores directly into the LHS. 7076122f3e6SDimitry Andric AggValueSlot LHSSlot = 7086122f3e6SDimitry Andric AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed, 7096122f3e6SDimitry Andric needsGC(E->getLHS()->getType()), 7106122f3e6SDimitry Andric AggValueSlot::IsAliased); 7112754fe60SDimitry Andric CGF.EmitAggExpr(E->getRHS(), LHSSlot, false); 712f22ef01cSRoman Divacky EmitFinalDestCopy(E, LHS, true); 713f22ef01cSRoman Divacky } 714f22ef01cSRoman Divacky 7152754fe60SDimitry Andric void AggExprEmitter:: 7162754fe60SDimitry Andric VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { 717f22ef01cSRoman Divacky llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true"); 718f22ef01cSRoman Divacky llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false"); 719f22ef01cSRoman Divacky llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end"); 720f22ef01cSRoman Divacky 7212754fe60SDimitry Andric // Bind the common expression if necessary. 7222754fe60SDimitry Andric CodeGenFunction::OpaqueValueMapping binding(CGF, E); 7232754fe60SDimitry Andric 7242754fe60SDimitry Andric CodeGenFunction::ConditionalEvaluation eval(CGF); 725f22ef01cSRoman Divacky CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock); 726f22ef01cSRoman Divacky 7272754fe60SDimitry Andric // Save whether the destination's lifetime is externally managed. 7286122f3e6SDimitry Andric bool isExternallyDestructed = Dest.isExternallyDestructed(); 7292754fe60SDimitry Andric 7302754fe60SDimitry Andric eval.begin(CGF); 731f22ef01cSRoman Divacky CGF.EmitBlock(LHSBlock); 7322754fe60SDimitry Andric Visit(E->getTrueExpr()); 7332754fe60SDimitry Andric eval.end(CGF); 734f22ef01cSRoman Divacky 7352754fe60SDimitry Andric assert(CGF.HaveInsertPoint() && "expression evaluation ended with no IP!"); 7362754fe60SDimitry Andric CGF.Builder.CreateBr(ContBlock); 737f22ef01cSRoman Divacky 7382754fe60SDimitry Andric // If the result of an agg expression is unused, then the emission 7392754fe60SDimitry Andric // of the LHS might need to create a destination slot. That's fine 7402754fe60SDimitry Andric // with us, and we can safely emit the RHS into the same slot, but 7416122f3e6SDimitry Andric // we shouldn't claim that it's already being destructed. 7426122f3e6SDimitry Andric Dest.setExternallyDestructed(isExternallyDestructed); 743f22ef01cSRoman Divacky 7442754fe60SDimitry Andric eval.begin(CGF); 745f22ef01cSRoman Divacky CGF.EmitBlock(RHSBlock); 7462754fe60SDimitry Andric Visit(E->getFalseExpr()); 7472754fe60SDimitry Andric eval.end(CGF); 748f22ef01cSRoman Divacky 749f22ef01cSRoman Divacky CGF.EmitBlock(ContBlock); 750f22ef01cSRoman Divacky } 751f22ef01cSRoman Divacky 752f22ef01cSRoman Divacky void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) { 753f22ef01cSRoman Divacky Visit(CE->getChosenSubExpr(CGF.getContext())); 754f22ef01cSRoman Divacky } 755f22ef01cSRoman Divacky 756f22ef01cSRoman Divacky void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { 757f22ef01cSRoman Divacky llvm::Value *ArgValue = CGF.EmitVAListRef(VE->getSubExpr()); 758f22ef01cSRoman Divacky llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType()); 759f22ef01cSRoman Divacky 760f22ef01cSRoman Divacky if (!ArgPtr) { 761f22ef01cSRoman Divacky CGF.ErrorUnsupported(VE, "aggregate va_arg expression"); 762f22ef01cSRoman Divacky return; 763f22ef01cSRoman Divacky } 764f22ef01cSRoman Divacky 765e580952dSDimitry Andric EmitFinalDestCopy(VE, CGF.MakeAddrLValue(ArgPtr, VE->getType())); 766f22ef01cSRoman Divacky } 767f22ef01cSRoman Divacky 768f22ef01cSRoman Divacky void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { 7692754fe60SDimitry Andric // Ensure that we have a slot, but if we already do, remember 7706122f3e6SDimitry Andric // whether it was externally destructed. 7716122f3e6SDimitry Andric bool wasExternallyDestructed = Dest.isExternallyDestructed(); 7722754fe60SDimitry Andric Dest = EnsureSlot(E->getType()); 7736122f3e6SDimitry Andric 7746122f3e6SDimitry Andric // We're going to push a destructor if there isn't already one. 7756122f3e6SDimitry Andric Dest.setExternallyDestructed(); 776f22ef01cSRoman Divacky 777f22ef01cSRoman Divacky Visit(E->getSubExpr()); 778f22ef01cSRoman Divacky 7796122f3e6SDimitry Andric // Push that destructor we promised. 7806122f3e6SDimitry Andric if (!wasExternallyDestructed) 781dff0c46cSDimitry Andric CGF.EmitCXXTemporary(E->getTemporary(), E->getType(), Dest.getAddr()); 782f22ef01cSRoman Divacky } 783f22ef01cSRoman Divacky 784f22ef01cSRoman Divacky void 785f22ef01cSRoman Divacky AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) { 7862754fe60SDimitry Andric AggValueSlot Slot = EnsureSlot(E->getType()); 7872754fe60SDimitry Andric CGF.EmitCXXConstructExpr(E, Slot); 788f22ef01cSRoman Divacky } 789f22ef01cSRoman Divacky 790dff0c46cSDimitry Andric void 791dff0c46cSDimitry Andric AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) { 792dff0c46cSDimitry Andric AggValueSlot Slot = EnsureSlot(E->getType()); 793dff0c46cSDimitry Andric CGF.EmitLambdaExpr(E, Slot); 794dff0c46cSDimitry Andric } 795dff0c46cSDimitry Andric 7962754fe60SDimitry Andric void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) { 797dff0c46cSDimitry Andric CGF.enterFullExpression(E); 798dff0c46cSDimitry Andric CodeGenFunction::RunCleanupsScope cleanups(CGF); 799dff0c46cSDimitry Andric Visit(E->getSubExpr()); 800f22ef01cSRoman Divacky } 801f22ef01cSRoman Divacky 802ffd1746dSEd Schouten void AggExprEmitter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { 8032754fe60SDimitry Andric QualType T = E->getType(); 8042754fe60SDimitry Andric AggValueSlot Slot = EnsureSlot(T); 80517a519f9SDimitry Andric EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddr(), T)); 806f22ef01cSRoman Divacky } 807f22ef01cSRoman Divacky 808f22ef01cSRoman Divacky void AggExprEmitter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { 8092754fe60SDimitry Andric QualType T = E->getType(); 8102754fe60SDimitry Andric AggValueSlot Slot = EnsureSlot(T); 81117a519f9SDimitry Andric EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddr(), T)); 8122754fe60SDimitry Andric } 813f22ef01cSRoman Divacky 8142754fe60SDimitry Andric /// isSimpleZero - If emitting this value will obviously just cause a store of 8152754fe60SDimitry Andric /// zero to memory, return true. This can return false if uncertain, so it just 8162754fe60SDimitry Andric /// handles simple cases. 8172754fe60SDimitry Andric static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) { 8183b0f4066SDimitry Andric E = E->IgnoreParens(); 8193b0f4066SDimitry Andric 8202754fe60SDimitry Andric // 0 8212754fe60SDimitry Andric if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E)) 8222754fe60SDimitry Andric return IL->getValue() == 0; 8232754fe60SDimitry Andric // +0.0 8242754fe60SDimitry Andric if (const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(E)) 8252754fe60SDimitry Andric return FL->getValue().isPosZero(); 8262754fe60SDimitry Andric // int() 8272754fe60SDimitry Andric if ((isa<ImplicitValueInitExpr>(E) || isa<CXXScalarValueInitExpr>(E)) && 8282754fe60SDimitry Andric CGF.getTypes().isZeroInitializable(E->getType())) 8292754fe60SDimitry Andric return true; 8302754fe60SDimitry Andric // (int*)0 - Null pointer expressions. 8312754fe60SDimitry Andric if (const CastExpr *ICE = dyn_cast<CastExpr>(E)) 8322754fe60SDimitry Andric return ICE->getCastKind() == CK_NullToPointer; 8332754fe60SDimitry Andric // '\0' 8342754fe60SDimitry Andric if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E)) 8352754fe60SDimitry Andric return CL->getValue() == 0; 8362754fe60SDimitry Andric 8372754fe60SDimitry Andric // Otherwise, hard case: conservatively return false. 8382754fe60SDimitry Andric return false; 839f22ef01cSRoman Divacky } 8402754fe60SDimitry Andric 841f22ef01cSRoman Divacky 842f22ef01cSRoman Divacky void 84317a519f9SDimitry Andric AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) { 84417a519f9SDimitry Andric QualType type = LV.getType(); 845f22ef01cSRoman Divacky // FIXME: Ignore result? 846f22ef01cSRoman Divacky // FIXME: Are initializers affected by volatile? 8472754fe60SDimitry Andric if (Dest.isZeroed() && isSimpleZero(E, CGF)) { 8482754fe60SDimitry Andric // Storing "i32 0" to a zero'd memory location is a noop. 8492754fe60SDimitry Andric } else if (isa<ImplicitValueInitExpr>(E)) { 85017a519f9SDimitry Andric EmitNullInitializationToLValue(LV); 85117a519f9SDimitry Andric } else if (type->isReferenceType()) { 852ffd1746dSEd Schouten RValue RV = CGF.EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0); 85317a519f9SDimitry Andric CGF.EmitStoreThroughLValue(RV, LV); 85417a519f9SDimitry Andric } else if (type->isAnyComplexType()) { 855f22ef01cSRoman Divacky CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false); 85617a519f9SDimitry Andric } else if (CGF.hasAggregateLLVMType(type)) { 8576122f3e6SDimitry Andric CGF.EmitAggExpr(E, AggValueSlot::forLValue(LV, 8586122f3e6SDimitry Andric AggValueSlot::IsDestructed, 8596122f3e6SDimitry Andric AggValueSlot::DoesNotNeedGCBarriers, 8606122f3e6SDimitry Andric AggValueSlot::IsNotAliased, 86117a519f9SDimitry Andric Dest.isZeroed())); 86217a519f9SDimitry Andric } else if (LV.isSimple()) { 86317a519f9SDimitry Andric CGF.EmitScalarInit(E, /*D=*/0, LV, /*Captured=*/false); 864f22ef01cSRoman Divacky } else { 86517a519f9SDimitry Andric CGF.EmitStoreThroughLValue(RValue::get(CGF.EmitScalarExpr(E)), LV); 866f22ef01cSRoman Divacky } 867f22ef01cSRoman Divacky } 868f22ef01cSRoman Divacky 86917a519f9SDimitry Andric void AggExprEmitter::EmitNullInitializationToLValue(LValue lv) { 87017a519f9SDimitry Andric QualType type = lv.getType(); 87117a519f9SDimitry Andric 8722754fe60SDimitry Andric // If the destination slot is already zeroed out before the aggregate is 8732754fe60SDimitry Andric // copied into it, we don't have to emit any zeros here. 87417a519f9SDimitry Andric if (Dest.isZeroed() && CGF.getTypes().isZeroInitializable(type)) 8752754fe60SDimitry Andric return; 8762754fe60SDimitry Andric 87717a519f9SDimitry Andric if (!CGF.hasAggregateLLVMType(type)) { 878dff0c46cSDimitry Andric // For non-aggregates, we can store zero. 87917a519f9SDimitry Andric llvm::Value *null = llvm::Constant::getNullValue(CGF.ConvertType(type)); 880dff0c46cSDimitry Andric // Note that the following is not equivalent to 881dff0c46cSDimitry Andric // EmitStoreThroughBitfieldLValue for ARC types. 882dff0c46cSDimitry Andric if (lv.isBitField()) { 883dff0c46cSDimitry Andric CGF.EmitStoreThroughBitfieldLValue(RValue::get(null), lv); 884dff0c46cSDimitry Andric } else { 885dff0c46cSDimitry Andric assert(lv.isSimple()); 886dff0c46cSDimitry Andric CGF.EmitStoreOfScalar(null, lv, /* isInitialization */ true); 887dff0c46cSDimitry Andric } 888f22ef01cSRoman Divacky } else { 889f22ef01cSRoman Divacky // There's a potential optimization opportunity in combining 890f22ef01cSRoman Divacky // memsets; that would be easy for arrays, but relatively 891f22ef01cSRoman Divacky // difficult for structures with the current code. 89217a519f9SDimitry Andric CGF.EmitNullInitialization(lv.getAddress(), lv.getType()); 893f22ef01cSRoman Divacky } 894f22ef01cSRoman Divacky } 895f22ef01cSRoman Divacky 896f22ef01cSRoman Divacky void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { 897f22ef01cSRoman Divacky #if 0 898f22ef01cSRoman Divacky // FIXME: Assess perf here? Figure out what cases are worth optimizing here 899f22ef01cSRoman Divacky // (Length of globals? Chunks of zeroed-out space?). 900f22ef01cSRoman Divacky // 901f22ef01cSRoman Divacky // If we can, prefer a copy from a global; this is a lot less code for long 902f22ef01cSRoman Divacky // globals, and it's easier for the current optimizers to analyze. 903f22ef01cSRoman Divacky if (llvm::Constant* C = CGF.CGM.EmitConstantExpr(E, E->getType(), &CGF)) { 904f22ef01cSRoman Divacky llvm::GlobalVariable* GV = 905f22ef01cSRoman Divacky new llvm::GlobalVariable(CGF.CGM.getModule(), C->getType(), true, 906f22ef01cSRoman Divacky llvm::GlobalValue::InternalLinkage, C, ""); 907e580952dSDimitry Andric EmitFinalDestCopy(E, CGF.MakeAddrLValue(GV, E->getType())); 908f22ef01cSRoman Divacky return; 909f22ef01cSRoman Divacky } 910f22ef01cSRoman Divacky #endif 9112754fe60SDimitry Andric if (E->hadArrayRangeDesignator()) 912f22ef01cSRoman Divacky CGF.ErrorUnsupported(E, "GNU array range designator extension"); 9132754fe60SDimitry Andric 914dff0c46cSDimitry Andric if (E->initializesStdInitializerList()) { 915dff0c46cSDimitry Andric EmitStdInitializerList(Dest.getAddr(), E); 916dff0c46cSDimitry Andric return; 917dff0c46cSDimitry Andric } 918dff0c46cSDimitry Andric 919cb4dff85SDimitry Andric AggValueSlot Dest = EnsureSlot(E->getType()); 920cb4dff85SDimitry Andric LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(), 921cb4dff85SDimitry Andric Dest.getAlignment()); 922f22ef01cSRoman Divacky 923f22ef01cSRoman Divacky // Handle initialization of an array. 924f22ef01cSRoman Divacky if (E->getType()->isArrayType()) { 925cb4dff85SDimitry Andric if (E->isStringLiteralInit()) 926cb4dff85SDimitry Andric return Visit(E->getInit(0)); 927f22ef01cSRoman Divacky 928dff0c46cSDimitry Andric QualType elementType = 929dff0c46cSDimitry Andric CGF.getContext().getAsArrayType(E->getType())->getElementType(); 930f22ef01cSRoman Divacky 931dff0c46cSDimitry Andric llvm::PointerType *APType = 932cb4dff85SDimitry Andric cast<llvm::PointerType>(Dest.getAddr()->getType()); 933dff0c46cSDimitry Andric llvm::ArrayType *AType = 934dff0c46cSDimitry Andric cast<llvm::ArrayType>(APType->getElementType()); 93517a519f9SDimitry Andric 936cb4dff85SDimitry Andric EmitArrayInit(Dest.getAddr(), AType, elementType, E); 937f22ef01cSRoman Divacky return; 938f22ef01cSRoman Divacky } 939f22ef01cSRoman Divacky 940f22ef01cSRoman Divacky assert(E->getType()->isRecordType() && "Only support structs/unions here!"); 941f22ef01cSRoman Divacky 942f22ef01cSRoman Divacky // Do struct initialization; this code just sets each individual member 943f22ef01cSRoman Divacky // to the approprate value. This makes bitfield support automatic; 944f22ef01cSRoman Divacky // the disadvantage is that the generated code is more difficult for 945f22ef01cSRoman Divacky // the optimizer, especially with bitfields. 946f22ef01cSRoman Divacky unsigned NumInitElements = E->getNumInits(); 94717a519f9SDimitry Andric RecordDecl *record = E->getType()->castAs<RecordType>()->getDecl(); 948e580952dSDimitry Andric 94917a519f9SDimitry Andric if (record->isUnion()) { 950f22ef01cSRoman Divacky // Only initialize one field of a union. The field itself is 951f22ef01cSRoman Divacky // specified by the initializer list. 952f22ef01cSRoman Divacky if (!E->getInitializedFieldInUnion()) { 953f22ef01cSRoman Divacky // Empty union; we have nothing to do. 954f22ef01cSRoman Divacky 955f22ef01cSRoman Divacky #ifndef NDEBUG 956f22ef01cSRoman Divacky // Make sure that it's really an empty and not a failure of 957f22ef01cSRoman Divacky // semantic analysis. 95817a519f9SDimitry Andric for (RecordDecl::field_iterator Field = record->field_begin(), 95917a519f9SDimitry Andric FieldEnd = record->field_end(); 960f22ef01cSRoman Divacky Field != FieldEnd; ++Field) 961f22ef01cSRoman Divacky assert(Field->isUnnamedBitfield() && "Only unnamed bitfields allowed"); 962f22ef01cSRoman Divacky #endif 963f22ef01cSRoman Divacky return; 964f22ef01cSRoman Divacky } 965f22ef01cSRoman Divacky 966f22ef01cSRoman Divacky // FIXME: volatility 967f22ef01cSRoman Divacky FieldDecl *Field = E->getInitializedFieldInUnion(); 968f22ef01cSRoman Divacky 969cb4dff85SDimitry Andric LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestLV, Field); 970f22ef01cSRoman Divacky if (NumInitElements) { 971f22ef01cSRoman Divacky // Store the initializer into the field 97217a519f9SDimitry Andric EmitInitializationToLValue(E->getInit(0), FieldLoc); 973f22ef01cSRoman Divacky } else { 9742754fe60SDimitry Andric // Default-initialize to null. 97517a519f9SDimitry Andric EmitNullInitializationToLValue(FieldLoc); 976f22ef01cSRoman Divacky } 977f22ef01cSRoman Divacky 978f22ef01cSRoman Divacky return; 979f22ef01cSRoman Divacky } 980f22ef01cSRoman Divacky 98117a519f9SDimitry Andric // We'll need to enter cleanup scopes in case any of the member 98217a519f9SDimitry Andric // initializers throw an exception. 9836122f3e6SDimitry Andric SmallVector<EHScopeStack::stable_iterator, 16> cleanups; 984dff0c46cSDimitry Andric llvm::Instruction *cleanupDominator = 0; 98517a519f9SDimitry Andric 986f22ef01cSRoman Divacky // Here we iterate over the fields; this makes it simpler to both 987f22ef01cSRoman Divacky // default-initialize fields and skip over unnamed fields. 98817a519f9SDimitry Andric unsigned curInitIndex = 0; 98917a519f9SDimitry Andric for (RecordDecl::field_iterator field = record->field_begin(), 99017a519f9SDimitry Andric fieldEnd = record->field_end(); 99117a519f9SDimitry Andric field != fieldEnd; ++field) { 99217a519f9SDimitry Andric // We're done once we hit the flexible array member. 99317a519f9SDimitry Andric if (field->getType()->isIncompleteArrayType()) 994f22ef01cSRoman Divacky break; 995f22ef01cSRoman Divacky 99617a519f9SDimitry Andric // Always skip anonymous bitfields. 99717a519f9SDimitry Andric if (field->isUnnamedBitfield()) 998f22ef01cSRoman Divacky continue; 999f22ef01cSRoman Divacky 100017a519f9SDimitry Andric // We're done if we reach the end of the explicit initializers, we 100117a519f9SDimitry Andric // have a zeroed object, and the rest of the fields are 100217a519f9SDimitry Andric // zero-initializable. 100317a519f9SDimitry Andric if (curInitIndex == NumInitElements && Dest.isZeroed() && 10042754fe60SDimitry Andric CGF.getTypes().isZeroInitializable(E->getType())) 10052754fe60SDimitry Andric break; 10062754fe60SDimitry Andric 1007cb4dff85SDimitry Andric 1008cb4dff85SDimitry Andric LValue LV = CGF.EmitLValueForFieldInitialization(DestLV, *field); 1009f22ef01cSRoman Divacky // We never generate write-barries for initialized fields. 101017a519f9SDimitry Andric LV.setNonGC(true); 10112754fe60SDimitry Andric 101217a519f9SDimitry Andric if (curInitIndex < NumInitElements) { 1013f22ef01cSRoman Divacky // Store the initializer into the field. 101417a519f9SDimitry Andric EmitInitializationToLValue(E->getInit(curInitIndex++), LV); 1015f22ef01cSRoman Divacky } else { 1016f22ef01cSRoman Divacky // We're out of initalizers; default-initialize to null 101717a519f9SDimitry Andric EmitNullInitializationToLValue(LV); 101817a519f9SDimitry Andric } 101917a519f9SDimitry Andric 102017a519f9SDimitry Andric // Push a destructor if necessary. 102117a519f9SDimitry Andric // FIXME: if we have an array of structures, all explicitly 102217a519f9SDimitry Andric // initialized, we can end up pushing a linear number of cleanups. 102317a519f9SDimitry Andric bool pushedCleanup = false; 102417a519f9SDimitry Andric if (QualType::DestructionKind dtorKind 102517a519f9SDimitry Andric = field->getType().isDestructedType()) { 102617a519f9SDimitry Andric assert(LV.isSimple()); 102717a519f9SDimitry Andric if (CGF.needsEHCleanup(dtorKind)) { 1028dff0c46cSDimitry Andric if (!cleanupDominator) 1029dff0c46cSDimitry Andric cleanupDominator = CGF.Builder.CreateUnreachable(); // placeholder 1030dff0c46cSDimitry Andric 103117a519f9SDimitry Andric CGF.pushDestroy(EHCleanup, LV.getAddress(), field->getType(), 103217a519f9SDimitry Andric CGF.getDestroyer(dtorKind), false); 103317a519f9SDimitry Andric cleanups.push_back(CGF.EHStack.stable_begin()); 103417a519f9SDimitry Andric pushedCleanup = true; 103517a519f9SDimitry Andric } 1036f22ef01cSRoman Divacky } 10372754fe60SDimitry Andric 10382754fe60SDimitry Andric // If the GEP didn't get used because of a dead zero init or something 10392754fe60SDimitry Andric // else, clean it up for -O0 builds and general tidiness. 104017a519f9SDimitry Andric if (!pushedCleanup && LV.isSimple()) 10412754fe60SDimitry Andric if (llvm::GetElementPtrInst *GEP = 104217a519f9SDimitry Andric dyn_cast<llvm::GetElementPtrInst>(LV.getAddress())) 10432754fe60SDimitry Andric if (GEP->use_empty()) 10442754fe60SDimitry Andric GEP->eraseFromParent(); 1045f22ef01cSRoman Divacky } 104617a519f9SDimitry Andric 104717a519f9SDimitry Andric // Deactivate all the partial cleanups in reverse order, which 104817a519f9SDimitry Andric // generally means popping them. 104917a519f9SDimitry Andric for (unsigned i = cleanups.size(); i != 0; --i) 1050dff0c46cSDimitry Andric CGF.DeactivateCleanupBlock(cleanups[i-1], cleanupDominator); 1051dff0c46cSDimitry Andric 1052dff0c46cSDimitry Andric // Destroy the placeholder if we made one. 1053dff0c46cSDimitry Andric if (cleanupDominator) 1054dff0c46cSDimitry Andric cleanupDominator->eraseFromParent(); 1055f22ef01cSRoman Divacky } 1056f22ef01cSRoman Divacky 1057f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 1058f22ef01cSRoman Divacky // Entry Points into this File 1059f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 1060f22ef01cSRoman Divacky 10612754fe60SDimitry Andric /// GetNumNonZeroBytesInInit - Get an approximate count of the number of 10622754fe60SDimitry Andric /// non-zero bytes that will be stored when outputting the initializer for the 10632754fe60SDimitry Andric /// specified initializer expression. 10643b0f4066SDimitry Andric static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { 10653b0f4066SDimitry Andric E = E->IgnoreParens(); 10662754fe60SDimitry Andric 10672754fe60SDimitry Andric // 0 and 0.0 won't require any non-zero stores! 10683b0f4066SDimitry Andric if (isSimpleZero(E, CGF)) return CharUnits::Zero(); 10692754fe60SDimitry Andric 10702754fe60SDimitry Andric // If this is an initlist expr, sum up the size of sizes of the (present) 10712754fe60SDimitry Andric // elements. If this is something weird, assume the whole thing is non-zero. 10722754fe60SDimitry Andric const InitListExpr *ILE = dyn_cast<InitListExpr>(E); 10732754fe60SDimitry Andric if (ILE == 0 || !CGF.getTypes().isZeroInitializable(ILE->getType())) 10743b0f4066SDimitry Andric return CGF.getContext().getTypeSizeInChars(E->getType()); 10752754fe60SDimitry Andric 10762754fe60SDimitry Andric // InitListExprs for structs have to be handled carefully. If there are 10772754fe60SDimitry Andric // reference members, we need to consider the size of the reference, not the 10782754fe60SDimitry Andric // referencee. InitListExprs for unions and arrays can't have references. 10792754fe60SDimitry Andric if (const RecordType *RT = E->getType()->getAs<RecordType>()) { 10802754fe60SDimitry Andric if (!RT->isUnionType()) { 10812754fe60SDimitry Andric RecordDecl *SD = E->getType()->getAs<RecordType>()->getDecl(); 10823b0f4066SDimitry Andric CharUnits NumNonZeroBytes = CharUnits::Zero(); 10832754fe60SDimitry Andric 10842754fe60SDimitry Andric unsigned ILEElement = 0; 10852754fe60SDimitry Andric for (RecordDecl::field_iterator Field = SD->field_begin(), 10862754fe60SDimitry Andric FieldEnd = SD->field_end(); Field != FieldEnd; ++Field) { 10872754fe60SDimitry Andric // We're done once we hit the flexible array member or run out of 10882754fe60SDimitry Andric // InitListExpr elements. 10892754fe60SDimitry Andric if (Field->getType()->isIncompleteArrayType() || 10902754fe60SDimitry Andric ILEElement == ILE->getNumInits()) 10912754fe60SDimitry Andric break; 10922754fe60SDimitry Andric if (Field->isUnnamedBitfield()) 10932754fe60SDimitry Andric continue; 10942754fe60SDimitry Andric 10952754fe60SDimitry Andric const Expr *E = ILE->getInit(ILEElement++); 10962754fe60SDimitry Andric 10972754fe60SDimitry Andric // Reference values are always non-null and have the width of a pointer. 10982754fe60SDimitry Andric if (Field->getType()->isReferenceType()) 10993b0f4066SDimitry Andric NumNonZeroBytes += CGF.getContext().toCharUnitsFromBits( 11006122f3e6SDimitry Andric CGF.getContext().getTargetInfo().getPointerWidth(0)); 11012754fe60SDimitry Andric else 11022754fe60SDimitry Andric NumNonZeroBytes += GetNumNonZeroBytesInInit(E, CGF); 11032754fe60SDimitry Andric } 11042754fe60SDimitry Andric 11052754fe60SDimitry Andric return NumNonZeroBytes; 11062754fe60SDimitry Andric } 11072754fe60SDimitry Andric } 11082754fe60SDimitry Andric 11092754fe60SDimitry Andric 11103b0f4066SDimitry Andric CharUnits NumNonZeroBytes = CharUnits::Zero(); 11112754fe60SDimitry Andric for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) 11122754fe60SDimitry Andric NumNonZeroBytes += GetNumNonZeroBytesInInit(ILE->getInit(i), CGF); 11132754fe60SDimitry Andric return NumNonZeroBytes; 11142754fe60SDimitry Andric } 11152754fe60SDimitry Andric 11162754fe60SDimitry Andric /// CheckAggExprForMemSetUse - If the initializer is large and has a lot of 11172754fe60SDimitry Andric /// zeros in it, emit a memset and avoid storing the individual zeros. 11182754fe60SDimitry Andric /// 11192754fe60SDimitry Andric static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E, 11202754fe60SDimitry Andric CodeGenFunction &CGF) { 11212754fe60SDimitry Andric // If the slot is already known to be zeroed, nothing to do. Don't mess with 11222754fe60SDimitry Andric // volatile stores. 11232754fe60SDimitry Andric if (Slot.isZeroed() || Slot.isVolatile() || Slot.getAddr() == 0) return; 11242754fe60SDimitry Andric 11253b0f4066SDimitry Andric // C++ objects with a user-declared constructor don't need zero'ing. 1126dff0c46cSDimitry Andric if (CGF.getContext().getLangOpts().CPlusPlus) 11273b0f4066SDimitry Andric if (const RecordType *RT = CGF.getContext() 11283b0f4066SDimitry Andric .getBaseElementType(E->getType())->getAs<RecordType>()) { 11293b0f4066SDimitry Andric const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); 11303b0f4066SDimitry Andric if (RD->hasUserDeclaredConstructor()) 11313b0f4066SDimitry Andric return; 11323b0f4066SDimitry Andric } 11333b0f4066SDimitry Andric 11342754fe60SDimitry Andric // If the type is 16-bytes or smaller, prefer individual stores over memset. 11353b0f4066SDimitry Andric std::pair<CharUnits, CharUnits> TypeInfo = 11363b0f4066SDimitry Andric CGF.getContext().getTypeInfoInChars(E->getType()); 11373b0f4066SDimitry Andric if (TypeInfo.first <= CharUnits::fromQuantity(16)) 11382754fe60SDimitry Andric return; 11392754fe60SDimitry Andric 11402754fe60SDimitry Andric // Check to see if over 3/4 of the initializer are known to be zero. If so, 11412754fe60SDimitry Andric // we prefer to emit memset + individual stores for the rest. 11423b0f4066SDimitry Andric CharUnits NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF); 11433b0f4066SDimitry Andric if (NumNonZeroBytes*4 > TypeInfo.first) 11442754fe60SDimitry Andric return; 11452754fe60SDimitry Andric 11462754fe60SDimitry Andric // Okay, it seems like a good idea to use an initial memset, emit the call. 11473b0f4066SDimitry Andric llvm::Constant *SizeVal = CGF.Builder.getInt64(TypeInfo.first.getQuantity()); 11483b0f4066SDimitry Andric CharUnits Align = TypeInfo.second; 11492754fe60SDimitry Andric 11502754fe60SDimitry Andric llvm::Value *Loc = Slot.getAddr(); 11512754fe60SDimitry Andric 1152dff0c46cSDimitry Andric Loc = CGF.Builder.CreateBitCast(Loc, CGF.Int8PtrTy); 11533b0f4066SDimitry Andric CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal, 11543b0f4066SDimitry Andric Align.getQuantity(), false); 11552754fe60SDimitry Andric 11562754fe60SDimitry Andric // Tell the AggExprEmitter that the slot is known zero. 11572754fe60SDimitry Andric Slot.setZeroed(); 11582754fe60SDimitry Andric } 11592754fe60SDimitry Andric 11602754fe60SDimitry Andric 11612754fe60SDimitry Andric 11622754fe60SDimitry Andric 1163f22ef01cSRoman Divacky /// EmitAggExpr - Emit the computation of the specified expression of aggregate 1164f22ef01cSRoman Divacky /// type. The result is computed into DestPtr. Note that if DestPtr is null, 1165f22ef01cSRoman Divacky /// the value of the aggregate expression is not needed. If VolatileDest is 1166f22ef01cSRoman Divacky /// true, DestPtr cannot be 0. 11672754fe60SDimitry Andric /// 11682754fe60SDimitry Andric /// \param IsInitializer - true if this evaluation is initializing an 11692754fe60SDimitry Andric /// object whose lifetime is already being managed. 11702754fe60SDimitry Andric void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot, 11712754fe60SDimitry Andric bool IgnoreResult) { 1172f22ef01cSRoman Divacky assert(E && hasAggregateLLVMType(E->getType()) && 1173f22ef01cSRoman Divacky "Invalid aggregate expression to emit"); 11742754fe60SDimitry Andric assert((Slot.getAddr() != 0 || Slot.isIgnored()) && 11752754fe60SDimitry Andric "slot has bits but no address"); 1176f22ef01cSRoman Divacky 11772754fe60SDimitry Andric // Optimize the slot if possible. 11782754fe60SDimitry Andric CheckAggExprForMemSetUse(Slot, E, *this); 11792754fe60SDimitry Andric 11802754fe60SDimitry Andric AggExprEmitter(*this, Slot, IgnoreResult).Visit(const_cast<Expr*>(E)); 1181f22ef01cSRoman Divacky } 1182f22ef01cSRoman Divacky 1183f22ef01cSRoman Divacky LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) { 1184f22ef01cSRoman Divacky assert(hasAggregateLLVMType(E->getType()) && "Invalid argument!"); 1185f22ef01cSRoman Divacky llvm::Value *Temp = CreateMemTemp(E->getType()); 1186e580952dSDimitry Andric LValue LV = MakeAddrLValue(Temp, E->getType()); 11876122f3e6SDimitry Andric EmitAggExpr(E, AggValueSlot::forLValue(LV, AggValueSlot::IsNotDestructed, 11886122f3e6SDimitry Andric AggValueSlot::DoesNotNeedGCBarriers, 11896122f3e6SDimitry Andric AggValueSlot::IsNotAliased)); 1190e580952dSDimitry Andric return LV; 1191f22ef01cSRoman Divacky } 1192f22ef01cSRoman Divacky 1193f22ef01cSRoman Divacky void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, 1194f22ef01cSRoman Divacky llvm::Value *SrcPtr, QualType Ty, 1195dff0c46cSDimitry Andric bool isVolatile, unsigned Alignment) { 1196f22ef01cSRoman Divacky assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex"); 1197f22ef01cSRoman Divacky 1198dff0c46cSDimitry Andric if (getContext().getLangOpts().CPlusPlus) { 1199f22ef01cSRoman Divacky if (const RecordType *RT = Ty->getAs<RecordType>()) { 1200f22ef01cSRoman Divacky CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl()); 1201f22ef01cSRoman Divacky assert((Record->hasTrivialCopyConstructor() || 12026122f3e6SDimitry Andric Record->hasTrivialCopyAssignment() || 12036122f3e6SDimitry Andric Record->hasTrivialMoveConstructor() || 12046122f3e6SDimitry Andric Record->hasTrivialMoveAssignment()) && 1205f22ef01cSRoman Divacky "Trying to aggregate-copy a type without a trivial copy " 1206f22ef01cSRoman Divacky "constructor or assignment operator"); 1207f22ef01cSRoman Divacky // Ignore empty classes in C++. 1208f22ef01cSRoman Divacky if (Record->isEmpty()) 1209f22ef01cSRoman Divacky return; 1210f22ef01cSRoman Divacky } 1211f22ef01cSRoman Divacky } 1212f22ef01cSRoman Divacky 1213f22ef01cSRoman Divacky // Aggregate assignment turns into llvm.memcpy. This is almost valid per 1214f22ef01cSRoman Divacky // C99 6.5.16.1p3, which states "If the value being stored in an object is 1215f22ef01cSRoman Divacky // read from another object that overlaps in anyway the storage of the first 1216f22ef01cSRoman Divacky // object, then the overlap shall be exact and the two objects shall have 1217f22ef01cSRoman Divacky // qualified or unqualified versions of a compatible type." 1218f22ef01cSRoman Divacky // 1219f22ef01cSRoman Divacky // memcpy is not defined if the source and destination pointers are exactly 1220f22ef01cSRoman Divacky // equal, but other compilers do this optimization, and almost every memcpy 1221f22ef01cSRoman Divacky // implementation handles this case safely. If there is a libc that does not 1222f22ef01cSRoman Divacky // safely handle this, we can add a target hook. 1223f22ef01cSRoman Divacky 1224f22ef01cSRoman Divacky // Get size and alignment info for this aggregate. 12253b0f4066SDimitry Andric std::pair<CharUnits, CharUnits> TypeInfo = 12263b0f4066SDimitry Andric getContext().getTypeInfoInChars(Ty); 1227f22ef01cSRoman Divacky 1228dff0c46cSDimitry Andric if (!Alignment) 1229dff0c46cSDimitry Andric Alignment = TypeInfo.second.getQuantity(); 1230dff0c46cSDimitry Andric 1231f22ef01cSRoman Divacky // FIXME: Handle variable sized types. 1232f22ef01cSRoman Divacky 1233f22ef01cSRoman Divacky // FIXME: If we have a volatile struct, the optimizer can remove what might 1234f22ef01cSRoman Divacky // appear to be `extra' memory ops: 1235f22ef01cSRoman Divacky // 1236f22ef01cSRoman Divacky // volatile struct { int i; } a, b; 1237f22ef01cSRoman Divacky // 1238f22ef01cSRoman Divacky // int main() { 1239f22ef01cSRoman Divacky // a = b; 1240f22ef01cSRoman Divacky // a = b; 1241f22ef01cSRoman Divacky // } 1242f22ef01cSRoman Divacky // 1243f22ef01cSRoman Divacky // we need to use a different call here. We use isVolatile to indicate when 1244f22ef01cSRoman Divacky // either the source or the destination is volatile. 1245f22ef01cSRoman Divacky 12466122f3e6SDimitry Andric llvm::PointerType *DPT = cast<llvm::PointerType>(DestPtr->getType()); 12476122f3e6SDimitry Andric llvm::Type *DBP = 12482754fe60SDimitry Andric llvm::Type::getInt8PtrTy(getLLVMContext(), DPT->getAddressSpace()); 12496122f3e6SDimitry Andric DestPtr = Builder.CreateBitCast(DestPtr, DBP); 1250f22ef01cSRoman Divacky 12516122f3e6SDimitry Andric llvm::PointerType *SPT = cast<llvm::PointerType>(SrcPtr->getType()); 12526122f3e6SDimitry Andric llvm::Type *SBP = 12532754fe60SDimitry Andric llvm::Type::getInt8PtrTy(getLLVMContext(), SPT->getAddressSpace()); 12546122f3e6SDimitry Andric SrcPtr = Builder.CreateBitCast(SrcPtr, SBP); 1255f22ef01cSRoman Divacky 125617a519f9SDimitry Andric // Don't do any of the memmove_collectable tests if GC isn't set. 1257dff0c46cSDimitry Andric if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { 125817a519f9SDimitry Andric // fall through 125917a519f9SDimitry Andric } else if (const RecordType *RecordTy = Ty->getAs<RecordType>()) { 1260ffd1746dSEd Schouten RecordDecl *Record = RecordTy->getDecl(); 1261ffd1746dSEd Schouten if (Record->hasObjectMember()) { 12623b0f4066SDimitry Andric CharUnits size = TypeInfo.first; 12636122f3e6SDimitry Andric llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); 12643b0f4066SDimitry Andric llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size.getQuantity()); 1265ffd1746dSEd Schouten CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr, 1266ffd1746dSEd Schouten SizeVal); 1267ffd1746dSEd Schouten return; 1268ffd1746dSEd Schouten } 126917a519f9SDimitry Andric } else if (Ty->isArrayType()) { 1270ffd1746dSEd Schouten QualType BaseType = getContext().getBaseElementType(Ty); 1271ffd1746dSEd Schouten if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) { 1272ffd1746dSEd Schouten if (RecordTy->getDecl()->hasObjectMember()) { 12733b0f4066SDimitry Andric CharUnits size = TypeInfo.first; 12746122f3e6SDimitry Andric llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); 12753b0f4066SDimitry Andric llvm::Value *SizeVal = 12763b0f4066SDimitry Andric llvm::ConstantInt::get(SizeTy, size.getQuantity()); 1277ffd1746dSEd Schouten CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr, 1278ffd1746dSEd Schouten SizeVal); 1279ffd1746dSEd Schouten return; 1280ffd1746dSEd Schouten } 1281ffd1746dSEd Schouten } 1282ffd1746dSEd Schouten } 1283ffd1746dSEd Schouten 12842754fe60SDimitry Andric Builder.CreateMemCpy(DestPtr, SrcPtr, 12853b0f4066SDimitry Andric llvm::ConstantInt::get(IntPtrTy, 12863b0f4066SDimitry Andric TypeInfo.first.getQuantity()), 1287dff0c46cSDimitry Andric Alignment, isVolatile); 1288dff0c46cSDimitry Andric } 1289dff0c46cSDimitry Andric 1290dff0c46cSDimitry Andric void CodeGenFunction::MaybeEmitStdInitializerListCleanup(llvm::Value *loc, 1291dff0c46cSDimitry Andric const Expr *init) { 1292dff0c46cSDimitry Andric const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(init); 1293dff0c46cSDimitry Andric if (cleanups) 1294dff0c46cSDimitry Andric init = cleanups->getSubExpr(); 1295dff0c46cSDimitry Andric 1296dff0c46cSDimitry Andric if (isa<InitListExpr>(init) && 1297dff0c46cSDimitry Andric cast<InitListExpr>(init)->initializesStdInitializerList()) { 1298dff0c46cSDimitry Andric // We initialized this std::initializer_list with an initializer list. 1299dff0c46cSDimitry Andric // A backing array was created. Push a cleanup for it. 1300dff0c46cSDimitry Andric EmitStdInitializerListCleanup(loc, cast<InitListExpr>(init)); 1301dff0c46cSDimitry Andric } 1302dff0c46cSDimitry Andric } 1303dff0c46cSDimitry Andric 1304dff0c46cSDimitry Andric static void EmitRecursiveStdInitializerListCleanup(CodeGenFunction &CGF, 1305dff0c46cSDimitry Andric llvm::Value *arrayStart, 1306dff0c46cSDimitry Andric const InitListExpr *init) { 1307dff0c46cSDimitry Andric // Check if there are any recursive cleanups to do, i.e. if we have 1308dff0c46cSDimitry Andric // std::initializer_list<std::initializer_list<obj>> list = {{obj()}}; 1309dff0c46cSDimitry Andric // then we need to destroy the inner array as well. 1310dff0c46cSDimitry Andric for (unsigned i = 0, e = init->getNumInits(); i != e; ++i) { 1311dff0c46cSDimitry Andric const InitListExpr *subInit = dyn_cast<InitListExpr>(init->getInit(i)); 1312dff0c46cSDimitry Andric if (!subInit || !subInit->initializesStdInitializerList()) 1313dff0c46cSDimitry Andric continue; 1314dff0c46cSDimitry Andric 1315dff0c46cSDimitry Andric // This one needs to be destroyed. Get the address of the std::init_list. 1316dff0c46cSDimitry Andric llvm::Value *offset = llvm::ConstantInt::get(CGF.SizeTy, i); 1317dff0c46cSDimitry Andric llvm::Value *loc = CGF.Builder.CreateInBoundsGEP(arrayStart, offset, 1318dff0c46cSDimitry Andric "std.initlist"); 1319dff0c46cSDimitry Andric CGF.EmitStdInitializerListCleanup(loc, subInit); 1320dff0c46cSDimitry Andric } 1321dff0c46cSDimitry Andric } 1322dff0c46cSDimitry Andric 1323dff0c46cSDimitry Andric void CodeGenFunction::EmitStdInitializerListCleanup(llvm::Value *loc, 1324dff0c46cSDimitry Andric const InitListExpr *init) { 1325dff0c46cSDimitry Andric ASTContext &ctx = getContext(); 1326dff0c46cSDimitry Andric QualType element = GetStdInitializerListElementType(init->getType()); 1327dff0c46cSDimitry Andric unsigned numInits = init->getNumInits(); 1328dff0c46cSDimitry Andric llvm::APInt size(ctx.getTypeSize(ctx.getSizeType()), numInits); 1329dff0c46cSDimitry Andric QualType array =ctx.getConstantArrayType(element, size, ArrayType::Normal, 0); 1330dff0c46cSDimitry Andric QualType arrayPtr = ctx.getPointerType(array); 1331dff0c46cSDimitry Andric llvm::Type *arrayPtrType = ConvertType(arrayPtr); 1332dff0c46cSDimitry Andric 1333dff0c46cSDimitry Andric // lvalue is the location of a std::initializer_list, which as its first 1334dff0c46cSDimitry Andric // element has a pointer to the array we want to destroy. 1335dff0c46cSDimitry Andric llvm::Value *startPointer = Builder.CreateStructGEP(loc, 0, "startPointer"); 1336dff0c46cSDimitry Andric llvm::Value *startAddress = Builder.CreateLoad(startPointer, "startAddress"); 1337dff0c46cSDimitry Andric 1338dff0c46cSDimitry Andric ::EmitRecursiveStdInitializerListCleanup(*this, startAddress, init); 1339dff0c46cSDimitry Andric 1340dff0c46cSDimitry Andric llvm::Value *arrayAddress = 1341dff0c46cSDimitry Andric Builder.CreateBitCast(startAddress, arrayPtrType, "arrayAddress"); 1342dff0c46cSDimitry Andric ::EmitStdInitializerListCleanup(*this, array, arrayAddress, init); 1343f22ef01cSRoman Divacky } 1344