diff options
Diffstat (limited to 'lib/CodeGen/CGExprAgg.cpp')
| -rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 78 | 
1 files changed, 54 insertions, 24 deletions
| diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 4cf94c033bb4..6fedf0efda9d 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -98,6 +98,11 @@ public:    //                            Visitor Methods    //===--------------------------------------------------------------------===// +  void Visit(Expr *E) { +    ApplyDebugLocation DL(CGF, E); +    StmtVisitor<AggExprEmitter>::Visit(E); +  } +    void VisitStmt(Stmt *S) {      CGF.ErrorUnsupported(S, "aggregate expression");    } @@ -207,7 +212,7 @@ void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) {    LValue LV = CGF.EmitLValue(E);    // If the type of the l-value is atomic, then do an atomic load. -  if (LV.getType()->isAtomicType()) { +  if (LV.getType()->isAtomicType() || CGF.LValueIsSuitableForInlineAtomic(LV)) {      CGF.EmitAtomicLoad(LV, E->getExprLoc(), Dest);      return;    } @@ -579,7 +584,12 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {    }    case CK_ToUnion: { -    if (Dest.isIgnored()) break; +    // Evaluate even if the destination is ignored. +    if (Dest.isIgnored()) { +      CGF.EmitAnyExpr(E->getSubExpr(), AggValueSlot::ignored(), +                      /*ignoreResult=*/true); +      break; +    }      // GCC union extension      QualType Ty = E->getSubExpr()->getType(); @@ -640,7 +650,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {          // Build a GEP to refer to the subobject.          llvm::Value *valueAddr = -            CGF.Builder.CreateStructGEP(valueDest.getAddr(), 0); +            CGF.Builder.CreateStructGEP(nullptr, valueDest.getAddr(), 0);          valueDest = AggValueSlot::forAddr(valueAddr,                                            valueDest.getAlignment(),                                            valueDest.getQualifiers(), @@ -661,7 +671,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {      CGF.EmitAggExpr(E->getSubExpr(), atomicSlot);      llvm::Value *valueAddr = -      Builder.CreateStructGEP(atomicSlot.getAddr(), 0); +        Builder.CreateStructGEP(nullptr, atomicSlot.getAddr(), 0);      RValue rvalue = RValue::getAggregate(valueAddr, atomicSlot.isVolatile());      return EmitFinalDestCopy(valueType, rvalue);    } @@ -736,7 +746,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {  }  void AggExprEmitter::VisitCallExpr(const CallExpr *E) { -  if (E->getCallReturnType()->isReferenceType()) { +  if (E->getCallReturnType(CGF.getContext())->isReferenceType()) {      EmitAggLoadOfLValue(E);      return;    } @@ -860,7 +870,8 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {      LValue LHS = CGF.EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);      // That copy is an atomic copy if the LHS is atomic. -    if (LHS.getType()->isAtomicType()) { +    if (LHS.getType()->isAtomicType() || +        CGF.LValueIsSuitableForInlineAtomic(LHS)) {        CGF.EmitAtomicStore(Dest.asRValue(), LHS, /*isInit*/ false);        return;      } @@ -877,7 +888,8 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {    // If we have an atomic type, evaluate into the destination and then    // do an atomic copy. -  if (LHS.getType()->isAtomicType()) { +  if (LHS.getType()->isAtomicType() || +      CGF.LValueIsSuitableForInlineAtomic(LHS)) {      EnsureDest(E->getRHS()->getType());      Visit(E->getRHS());      CGF.EmitAtomicStore(Dest.asRValue(), LHS, /*isInit*/ false); @@ -909,16 +921,16 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {    // Bind the common expression if necessary.    CodeGenFunction::OpaqueValueMapping binding(CGF, E); -  RegionCounter Cnt = CGF.getPGORegionCounter(E);    CodeGenFunction::ConditionalEvaluation eval(CGF); -  CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock, Cnt.getCount()); +  CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock, +                           CGF.getProfileCount(E));    // Save whether the destination's lifetime is externally managed.    bool isExternallyDestructed = Dest.isExternallyDestructed();    eval.begin(CGF);    CGF.EmitBlock(LHSBlock); -  Cnt.beginRegion(Builder); +  CGF.incrementProfileCounter(E);    Visit(E->getTrueExpr());    eval.end(CGF); @@ -1408,7 +1420,8 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,        assert((Record->hasTrivialCopyConstructor() ||                 Record->hasTrivialCopyAssignment() ||                Record->hasTrivialMoveConstructor() || -              Record->hasTrivialMoveAssignment()) && +              Record->hasTrivialMoveAssignment() || +              Record->isUnion()) &&               "Trying to aggregate-copy a type without a trivial copy/move "               "constructor or assignment operator");        // Ignore empty classes in C++. @@ -1439,7 +1452,34 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,    if (alignment.isZero())      alignment = TypeInfo.second; -  // FIXME: Handle variable sized types. +  llvm::Value *SizeVal = nullptr; +  if (TypeInfo.first.isZero()) { +    // But note that getTypeInfo returns 0 for a VLA. +    if (auto *VAT = dyn_cast_or_null<VariableArrayType>( +            getContext().getAsArrayType(Ty))) { +      QualType BaseEltTy; +      SizeVal = emitArrayLength(VAT, BaseEltTy, DestPtr); +      TypeInfo = getContext().getTypeInfoDataSizeInChars(BaseEltTy); +      std::pair<CharUnits, CharUnits> LastElementTypeInfo; +      if (!isAssignment) +        LastElementTypeInfo = getContext().getTypeInfoInChars(BaseEltTy); +      assert(!TypeInfo.first.isZero()); +      SizeVal = Builder.CreateNUWMul( +          SizeVal, +          llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity())); +      if (!isAssignment) { +        SizeVal = Builder.CreateNUWSub( +            SizeVal, +            llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity())); +        SizeVal = Builder.CreateNUWAdd( +            SizeVal, llvm::ConstantInt::get( +                         SizeTy, LastElementTypeInfo.first.getQuantity())); +      } +    } +  } +  if (!SizeVal) { +    SizeVal = llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity()); +  }    // FIXME: If we have a volatile struct, the optimizer can remove what might    // appear to be `extra' memory ops: @@ -1470,9 +1510,6 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,    } else if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {      RecordDecl *Record = RecordTy->getDecl();      if (Record->hasObjectMember()) { -      CharUnits size = TypeInfo.first; -      llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); -      llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size.getQuantity());        CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,                                                       SizeVal);        return; @@ -1481,10 +1518,6 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,      QualType BaseType = getContext().getBaseElementType(Ty);      if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {        if (RecordTy->getDecl()->hasObjectMember()) { -        CharUnits size = TypeInfo.first; -        llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); -        llvm::Value *SizeVal =  -          llvm::ConstantInt::get(SizeTy, size.getQuantity());          CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,                                                         SizeVal);          return; @@ -1497,9 +1530,6 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,    // the optimizer wishes to expand it in to scalar memory operations.    llvm::MDNode *TBAAStructTag = CGM.getTBAAStructInfo(Ty); -  Builder.CreateMemCpy(DestPtr, SrcPtr, -                       llvm::ConstantInt::get(IntPtrTy,  -                                              TypeInfo.first.getQuantity()), -                       alignment.getQuantity(), isVolatile, -                       /*TBAATag=*/nullptr, TBAAStructTag); +  Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, alignment.getQuantity(), +                       isVolatile, /*TBAATag=*/nullptr, TBAAStructTag);  } | 
