diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 80 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 35 |
3 files changed, 121 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index c0989883e17..d756eca64f1 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -164,6 +164,7 @@ public: void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO); void VisitChooseExpr(const ChooseExpr *CE); void VisitInitListExpr(InitListExpr *E); + void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E); void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); void VisitNoInitExpr(NoInitExpr *E) { } // Do nothing. void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { @@ -1308,6 +1309,85 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { cleanupDominator->eraseFromParent(); } +void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { + // Emit the common subexpression. + CodeGenFunction::OpaqueValueMapping binding(CGF, E->getCommonExpr()); + + Address destPtr = EnsureSlot(E->getType()).getAddress(); + uint64_t numElements = E->getArraySize().getZExtValue(); + + if (!numElements) + return; + + // FIXME: Dig through nested ArrayInitLoopExprs to find the overall array + // size, and only emit a single loop for a multidimensional array. + + // destPtr is an array*. Construct an elementType* by drilling down a level. + llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); + llvm::Value *indices[] = {zero, zero}; + llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getPointer(), indices, + "arrayinit.begin"); + + QualType elementType = E->getSubExpr()->getType(); + CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); + CharUnits elementAlign = + destPtr.getAlignment().alignmentOfArrayElement(elementSize); + + // Prepare for a cleanup. + QualType::DestructionKind dtorKind = elementType.isDestructedType(); + Address endOfInit = Address::invalid(); + EHScopeStack::stable_iterator cleanup; + llvm::Instruction *cleanupDominator = nullptr; + if (CGF.needsEHCleanup(dtorKind)) { + endOfInit = CGF.CreateTempAlloca(begin->getType(), CGF.getPointerAlign(), + "arrayinit.endOfInit"); + CGF.pushIrregularPartialArrayCleanup(begin, endOfInit, elementType, + elementAlign, + CGF.getDestroyer(dtorKind)); + cleanup = CGF.EHStack.stable_begin(); + } else { + dtorKind = QualType::DK_none; + } + + llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); + llvm::BasicBlock *bodyBB = CGF.createBasicBlock("arrayinit.body"); + + // Jump into the body. + CGF.EmitBlock(bodyBB); + llvm::PHINode *index = + Builder.CreatePHI(zero->getType(), 2, "arrayinit.index"); + index->addIncoming(zero, entryBB); + llvm::Value *element = Builder.CreateInBoundsGEP(begin, index); + + // Tell the EH cleanup that we finished with the last element. + if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit); + + // Emit the actual filler expression. + { + CodeGenFunction::ArrayInitLoopExprScope Scope(CGF, index); + LValue elementLV = + CGF.MakeAddrLValue(Address(element, elementAlign), elementType); + EmitInitializationToLValue(E->getSubExpr(), elementLV); + } + + // Move on to the next element. + llvm::Value *nextIndex = Builder.CreateNUWAdd( + index, llvm::ConstantInt::get(CGF.SizeTy, 1), "arrayinit.next"); + index->addIncoming(nextIndex, Builder.GetInsertBlock()); + + // Leave the loop if we're done. + llvm::Value *done = Builder.CreateICmpEQ( + nextIndex, llvm::ConstantInt::get(CGF.SizeTy, numElements), + "arrayinit.done"); + llvm::BasicBlock *endBB = CGF.createBasicBlock("arrayinit.end"); + Builder.CreateCondBr(done, endBB, bodyBB); + + CGF.EmitBlock(endBB); + + // Leave the partial-array cleanup if we entered one. + if (dtorKind) CGF.DeactivateCleanupBlock(cleanup, cleanupDominator); +} + void AggExprEmitter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) { AggValueSlot Dest = EnsureSlot(E->getType()); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 2b54370c296..c15e580cd30 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -311,6 +311,12 @@ public: Value *VisitInitListExpr(InitListExpr *E); + Value *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { + assert(CGF.getArrayInitIndex() && + "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?"); + return CGF.getArrayInitIndex(); + } + Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { return EmitNullValue(E->getType()); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 071bcb86866..b9b33a8783d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -918,6 +918,17 @@ public: e->getCommon()); } + /// Build the opaque value mapping for an OpaqueValueExpr whose source + /// expression is set to the expression the OVE represents. + OpaqueValueMapping(CodeGenFunction &CGF, const OpaqueValueExpr *OV) + : CGF(CGF) { + if (OV) { + assert(OV->getSourceExpr() && "wrong form of OpaqueValueMapping used " + "for OVE with no source expression"); + Data = OpaqueValueMappingData::bind(CGF, OV, OV->getSourceExpr()); + } + } + OpaqueValueMapping(CodeGenFunction &CGF, const OpaqueValueExpr *opaqueValue, LValue lvalue) @@ -1183,6 +1194,23 @@ public: CharUnits OldCXXThisAlignment; }; + /// The scope of an ArrayInitLoopExpr. Within this scope, the value of the + /// current loop index is overridden. + class ArrayInitLoopExprScope { + public: + ArrayInitLoopExprScope(CodeGenFunction &CGF, llvm::Value *Index) + : CGF(CGF), OldArrayInitIndex(CGF.ArrayInitIndex) { + CGF.ArrayInitIndex = Index; + } + ~ArrayInitLoopExprScope() { + CGF.ArrayInitIndex = OldArrayInitIndex; + } + + private: + CodeGenFunction &CGF; + llvm::Value *OldArrayInitIndex; + }; + class InlinedInheritingConstructorScope { public: InlinedInheritingConstructorScope(CodeGenFunction &CGF, GlobalDecl GD) @@ -1251,6 +1279,10 @@ private: /// this expression. Address CXXDefaultInitExprThis = Address::invalid(); + /// The current array initialization index when evaluating an + /// ArrayInitIndexExpr within an ArrayInitLoopExpr. + llvm::Value *ArrayInitIndex = nullptr; + /// The values of function arguments to use when evaluating /// CXXInheritedCtorInitExprs within this context. CallArgList CXXInheritedCtorInitExprArgs; @@ -1953,6 +1985,9 @@ public: return it->second; } + /// Get the index of the current ArrayInitLoopExpr, if any. + llvm::Value *getArrayInitIndex() { return ArrayInitIndex; } + /// getAccessedFieldNo - Given an encoded value and a result number, return /// the input field number being accessed. static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts); |