diff options
Diffstat (limited to 'lib/CodeGen/CGExprAgg.cpp')
| -rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 285 | 
1 files changed, 79 insertions, 206 deletions
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index b974e1dcc6820..9d0f3a9661a68 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -29,14 +29,6 @@ using namespace CodeGen;  //                        Aggregate Expression Emitter  //===----------------------------------------------------------------------===// -llvm::Value *AggValueSlot::getPaddedAtomicAddr() const { -  assert(isValueOfAtomic()); -  llvm::GEPOperator *op = cast<llvm::GEPOperator>(getAddr()); -  assert(op->getNumIndices() == 2); -  assert(op->hasAllZeroIndices()); -  return op->getPointerOperand(); -} -  namespace  {  class AggExprEmitter : public StmtVisitor<AggExprEmitter> {    CodeGenFunction &CGF; @@ -91,7 +83,6 @@ public:    void EmitMoveFromReturnSlot(const Expr *E, RValue Src); -  void EmitStdInitializerList(llvm::Value *DestPtr, InitListExpr *InitList);    void EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,                       QualType elementType, InitListExpr *E); @@ -177,6 +168,7 @@ public:    void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);    void VisitCXXConstructExpr(const CXXConstructExpr *E);    void VisitLambdaExpr(LambdaExpr *E); +  void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E);    void VisitExprWithCleanups(ExprWithCleanups *E);    void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);    void VisitCXXTypeidExpr(CXXTypeidExpr *E) { EmitAggLoadOfLValue(E); } @@ -202,38 +194,6 @@ public:      CGF.EmitAtomicExpr(E, EnsureSlot(E->getType()).getAddr());    }  }; - -/// A helper class for emitting expressions into the value sub-object -/// of a padded atomic type. -class ValueDestForAtomic { -  AggValueSlot Dest; -public: -  ValueDestForAtomic(CodeGenFunction &CGF, AggValueSlot dest, QualType type) -    : Dest(dest) { -    assert(!Dest.isValueOfAtomic()); -    if (!Dest.isIgnored() && CGF.CGM.isPaddedAtomicType(type)) { -      llvm::Value *valueAddr = CGF.Builder.CreateStructGEP(Dest.getAddr(), 0); -      Dest = AggValueSlot::forAddr(valueAddr, -                                   Dest.getAlignment(), -                                   Dest.getQualifiers(), -                                   Dest.isExternallyDestructed(), -                                   Dest.requiresGCollection(), -                                   Dest.isPotentiallyAliased(), -                                   Dest.isZeroed(), -                                   AggValueSlot::IsValueOfAtomic); -    } -  } - -  const AggValueSlot &getDest() const { return Dest; } - -  ~ValueDestForAtomic() { -    // Kill the GEP if we made one and it didn't end up used. -    if (Dest.isValueOfAtomic()) { -      llvm::Instruction *addr = cast<llvm::GetElementPtrInst>(Dest.getAddr()); -      if (addr->use_empty()) addr->eraseFromParent(); -    } -  } -};  }  // end anonymous namespace.  //===----------------------------------------------------------------------===// @@ -248,8 +208,7 @@ void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) {    // If the type of the l-value is atomic, then do an atomic load.    if (LV.getType()->isAtomicType()) { -    ValueDestForAtomic valueDest(CGF, Dest, LV.getType()); -    CGF.EmitAtomicLoad(LV, valueDest.getDest()); +    CGF.EmitAtomicLoad(LV, E->getExprLoc(), Dest);      return;    } @@ -345,89 +304,70 @@ void AggExprEmitter::EmitCopy(QualType type, const AggValueSlot &dest,                          std::min(dest.getAlignment(), src.getAlignment()));  } -static QualType GetStdInitializerListElementType(QualType T) { -  // Just assume that this is really std::initializer_list. -  ClassTemplateSpecializationDecl *specialization = -      cast<ClassTemplateSpecializationDecl>(T->castAs<RecordType>()->getDecl()); -  return specialization->getTemplateArgs()[0].getAsType(); -} - -/// \brief Prepare cleanup for the temporary array. -static void EmitStdInitializerListCleanup(CodeGenFunction &CGF, -                                          QualType arrayType, -                                          llvm::Value *addr, -                                          const InitListExpr *initList) { -  QualType::DestructionKind dtorKind = arrayType.isDestructedType(); -  if (!dtorKind) -    return; // Type doesn't need destroying. -  if (dtorKind != QualType::DK_cxx_destructor) { -    CGF.ErrorUnsupported(initList, "ObjC ARC type in initializer_list"); -    return; -  } - -  CodeGenFunction::Destroyer *destroyer = CGF.getDestroyer(dtorKind); -  CGF.pushDestroy(NormalAndEHCleanup, addr, arrayType, destroyer, -                  /*EHCleanup=*/true); -} -  /// \brief Emit the initializer for a std::initializer_list initialized with a  /// real initializer list. -void AggExprEmitter::EmitStdInitializerList(llvm::Value *destPtr, -                                            InitListExpr *initList) { -  // We emit an array containing the elements, then have the init list point -  // at the array. -  ASTContext &ctx = CGF.getContext(); -  unsigned numInits = initList->getNumInits(); -  QualType element = GetStdInitializerListElementType(initList->getType()); -  llvm::APInt size(ctx.getTypeSize(ctx.getSizeType()), numInits); -  QualType array = ctx.getConstantArrayType(element, size, ArrayType::Normal,0); -  llvm::Type *LTy = CGF.ConvertTypeForMem(array); -  llvm::AllocaInst *alloc = CGF.CreateTempAlloca(LTy); -  alloc->setAlignment(ctx.getTypeAlignInChars(array).getQuantity()); -  alloc->setName(".initlist."); - -  EmitArrayInit(alloc, cast<llvm::ArrayType>(LTy), element, initList); - -  // FIXME: The diagnostics are somewhat out of place here. -  RecordDecl *record = initList->getType()->castAs<RecordType>()->getDecl(); -  RecordDecl::field_iterator field = record->field_begin(); -  if (field == record->field_end()) { -    CGF.ErrorUnsupported(initList, "weird std::initializer_list"); +void +AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { +  // Emit an array containing the elements.  The array is externally destructed +  // if the std::initializer_list object is. +  ASTContext &Ctx = CGF.getContext(); +  LValue Array = CGF.EmitLValue(E->getSubExpr()); +  assert(Array.isSimple() && "initializer_list array not a simple lvalue"); +  llvm::Value *ArrayPtr = Array.getAddress(); + +  const ConstantArrayType *ArrayType = +      Ctx.getAsConstantArrayType(E->getSubExpr()->getType()); +  assert(ArrayType && "std::initializer_list constructed from non-array"); + +  // FIXME: Perform the checks on the field types in SemaInit. +  RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl(); +  RecordDecl::field_iterator Field = Record->field_begin(); +  if (Field == Record->field_end()) { +    CGF.ErrorUnsupported(E, "weird std::initializer_list");      return;    } -  QualType elementPtr = ctx.getPointerType(element.withConst()); -    // Start pointer. -  if (!ctx.hasSameType(field->getType(), elementPtr)) { -    CGF.ErrorUnsupported(initList, "weird std::initializer_list"); +  if (!Field->getType()->isPointerType() || +      !Ctx.hasSameType(Field->getType()->getPointeeType(), +                       ArrayType->getElementType())) { +    CGF.ErrorUnsupported(E, "weird std::initializer_list");      return;    } -  LValue DestLV = CGF.MakeNaturalAlignAddrLValue(destPtr, initList->getType()); -  LValue start = CGF.EmitLValueForFieldInitialization(DestLV, *field); -  llvm::Value *arrayStart = Builder.CreateStructGEP(alloc, 0, "arraystart"); -  CGF.EmitStoreThroughLValue(RValue::get(arrayStart), start); -  ++field; - -  if (field == record->field_end()) { -    CGF.ErrorUnsupported(initList, "weird std::initializer_list"); + +  AggValueSlot Dest = EnsureSlot(E->getType()); +  LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(), +                                     Dest.getAlignment()); +  LValue Start = CGF.EmitLValueForFieldInitialization(DestLV, *Field); +  llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0); +  llvm::Value *IdxStart[] = { Zero, Zero }; +  llvm::Value *ArrayStart = +      Builder.CreateInBoundsGEP(ArrayPtr, IdxStart, "arraystart"); +  CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start); +  ++Field; + +  if (Field == Record->field_end()) { +    CGF.ErrorUnsupported(E, "weird std::initializer_list");      return;    } -  LValue endOrLength = CGF.EmitLValueForFieldInitialization(DestLV, *field); -  if (ctx.hasSameType(field->getType(), elementPtr)) { + +  llvm::Value *Size = Builder.getInt(ArrayType->getSize()); +  LValue EndOrLength = CGF.EmitLValueForFieldInitialization(DestLV, *Field); +  if (Field->getType()->isPointerType() && +      Ctx.hasSameType(Field->getType()->getPointeeType(), +                      ArrayType->getElementType())) {      // End pointer. -    llvm::Value *arrayEnd = Builder.CreateStructGEP(alloc,numInits, "arrayend"); -    CGF.EmitStoreThroughLValue(RValue::get(arrayEnd), endOrLength); -  } else if(ctx.hasSameType(field->getType(), ctx.getSizeType())) { +    llvm::Value *IdxEnd[] = { Zero, Size }; +    llvm::Value *ArrayEnd = +        Builder.CreateInBoundsGEP(ArrayPtr, IdxEnd, "arrayend"); +    CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength); +  } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) {      // Length. -    CGF.EmitStoreThroughLValue(RValue::get(Builder.getInt(size)), endOrLength); +    CGF.EmitStoreThroughLValue(RValue::get(Size), EndOrLength);    } else { -    CGF.ErrorUnsupported(initList, "weird std::initializer_list"); +    CGF.ErrorUnsupported(E, "weird std::initializer_list");      return;    } - -  if (!Dest.isExternallyDestructed()) -    EmitStdInitializerListCleanup(CGF, array, alloc, initList);  }  /// \brief Emit initialization of an array from an initializer list. @@ -490,15 +430,8 @@ void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,        if (endOfInit) Builder.CreateStore(element, endOfInit);      } -    // If these are nested std::initializer_list inits, do them directly, -    // because they are conceptually the same "location". -    InitListExpr *initList = dyn_cast<InitListExpr>(E->getInit(i)); -    if (initList && initList->initializesStdInitializerList()) { -      EmitStdInitializerList(element, initList); -    } else { -      LValue elementLV = CGF.MakeAddrLValue(element, elementType); -      EmitInitializationToLValue(E->getInit(i), elementLV); -    } +    LValue elementLV = CGF.MakeAddrLValue(element, elementType); +    EmitInitializationToLValue(E->getInit(i), elementLV);    }    // Check whether there's a non-trivial array-fill expression. @@ -679,34 +612,33 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {      }      // If we're converting an r-value of non-atomic type to an r-value -    // of atomic type, just make an atomic temporary, emit into that, -    // and then copy the value out.  (FIXME: do we need to -    // zero-initialize it first?) +    // of atomic type, just emit directly into the relevant sub-object.      if (isToAtomic) { -      ValueDestForAtomic valueDest(CGF, Dest, atomicType); -      CGF.EmitAggExpr(E->getSubExpr(), valueDest.getDest()); +      AggValueSlot valueDest = Dest; +      if (!valueDest.isIgnored() && CGF.CGM.isPaddedAtomicType(atomicType)) { +        // Zero-initialize.  (Strictly speaking, we only need to intialize +        // the padding at the end, but this is simpler.) +        if (!Dest.isZeroed()) +          CGF.EmitNullInitialization(Dest.getAddr(), atomicType); + +        // Build a GEP to refer to the subobject. +        llvm::Value *valueAddr = +            CGF.Builder.CreateStructGEP(valueDest.getAddr(), 0); +        valueDest = AggValueSlot::forAddr(valueAddr, +                                          valueDest.getAlignment(), +                                          valueDest.getQualifiers(), +                                          valueDest.isExternallyDestructed(), +                                          valueDest.requiresGCollection(), +                                          valueDest.isPotentiallyAliased(), +                                          AggValueSlot::IsZeroed); +      } +       +      CGF.EmitAggExpr(E->getSubExpr(), valueDest);        return;      }      // Otherwise, we're converting an atomic type to a non-atomic type. - -    // If the dest is a value-of-atomic subobject, drill back out. -    if (Dest.isValueOfAtomic()) { -      AggValueSlot atomicSlot = -        AggValueSlot::forAddr(Dest.getPaddedAtomicAddr(), -                              Dest.getAlignment(), -                              Dest.getQualifiers(), -                              Dest.isExternallyDestructed(), -                              Dest.requiresGCollection(), -                              Dest.isPotentiallyAliased(), -                              Dest.isZeroed(), -                              AggValueSlot::IsNotValueOfAtomic); -      CGF.EmitAggExpr(E->getSubExpr(), atomicSlot); -      return; -    } - -    // Otherwise, make an atomic temporary, emit into that, and then -    // copy the value out. +    // Make an atomic temporary, emit into that, and then copy the value out.      AggValueSlot atomicSlot =        CGF.CreateAggTemp(atomicType, "atomic-to-nonatomic.temp");      CGF.EmitAggExpr(E->getSubExpr(), atomicSlot); @@ -988,7 +920,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {  }  void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) { -  Visit(CE->getChosenSubExpr(CGF.getContext())); +  Visit(CE->getChosenSubExpr());  }  void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { @@ -1078,7 +1010,7 @@ static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) {  void  -AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) { +AggExprEmitter::EmitInitializationToLValue(Expr *E, LValue LV) {    QualType type = LV.getType();    // FIXME: Ignore result?    // FIXME: Are initializers affected by volatile? @@ -1088,7 +1020,7 @@ AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) {    } else if (isa<ImplicitValueInitExpr>(E) || isa<CXXScalarValueInitExpr>(E)) {      return EmitNullInitializationToLValue(LV);    } else if (type->isReferenceType()) { -    RValue RV = CGF.EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0); +    RValue RV = CGF.EmitReferenceBindingToExpr(E);      return CGF.EmitStoreThroughLValue(RV, LV);    } @@ -1159,12 +1091,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {    if (E->hadArrayRangeDesignator())      CGF.ErrorUnsupported(E, "GNU array range designator extension"); -  if (E->initializesStdInitializerList()) { -    EmitStdInitializerList(Dest.getAddr(), E); -    return; -  } -    AggValueSlot Dest = EnsureSlot(E->getType()); +    LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),                                       Dest.getAlignment()); @@ -1545,58 +1473,3 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,                         alignment.getQuantity(), isVolatile,                         /*TBAATag=*/0, TBAAStructTag);  } - -void CodeGenFunction::MaybeEmitStdInitializerListCleanup(llvm::Value *loc, -                                                         const Expr *init) { -  const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(init); -  if (cleanups) -    init = cleanups->getSubExpr(); - -  if (isa<InitListExpr>(init) && -      cast<InitListExpr>(init)->initializesStdInitializerList()) { -    // We initialized this std::initializer_list with an initializer list. -    // A backing array was created. Push a cleanup for it. -    EmitStdInitializerListCleanup(loc, cast<InitListExpr>(init)); -  } -} - -static void EmitRecursiveStdInitializerListCleanup(CodeGenFunction &CGF, -                                                   llvm::Value *arrayStart, -                                                   const InitListExpr *init) { -  // Check if there are any recursive cleanups to do, i.e. if we have -  //   std::initializer_list<std::initializer_list<obj>> list = {{obj()}}; -  // then we need to destroy the inner array as well. -  for (unsigned i = 0, e = init->getNumInits(); i != e; ++i) { -    const InitListExpr *subInit = dyn_cast<InitListExpr>(init->getInit(i)); -    if (!subInit || !subInit->initializesStdInitializerList()) -      continue; - -    // This one needs to be destroyed. Get the address of the std::init_list. -    llvm::Value *offset = llvm::ConstantInt::get(CGF.SizeTy, i); -    llvm::Value *loc = CGF.Builder.CreateInBoundsGEP(arrayStart, offset, -                                                 "std.initlist"); -    CGF.EmitStdInitializerListCleanup(loc, subInit); -  } -} - -void CodeGenFunction::EmitStdInitializerListCleanup(llvm::Value *loc, -                                                    const InitListExpr *init) { -  ASTContext &ctx = getContext(); -  QualType element = GetStdInitializerListElementType(init->getType()); -  unsigned numInits = init->getNumInits(); -  llvm::APInt size(ctx.getTypeSize(ctx.getSizeType()), numInits); -  QualType array =ctx.getConstantArrayType(element, size, ArrayType::Normal, 0); -  QualType arrayPtr = ctx.getPointerType(array); -  llvm::Type *arrayPtrType = ConvertType(arrayPtr); - -  // lvalue is the location of a std::initializer_list, which as its first -  // element has a pointer to the array we want to destroy. -  llvm::Value *startPointer = Builder.CreateStructGEP(loc, 0, "startPointer"); -  llvm::Value *startAddress = Builder.CreateLoad(startPointer, "startAddress"); - -  ::EmitRecursiveStdInitializerListCleanup(*this, startAddress, init); - -  llvm::Value *arrayAddress = -      Builder.CreateBitCast(startAddress, arrayPtrType, "arrayAddress"); -  ::EmitStdInitializerListCleanup(*this, array, arrayAddress, init); -}  | 
