summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-12-12 02:53:20 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-12-12 02:53:20 +0000
commit410306bf6ed906af77978caa199e5d96376bae66 (patch)
tree811f32246733190c960c7785c3dd02587d43be1d /clang/lib/CodeGen
parent8c9cc8c86be80abd4224341314725d03551460d6 (diff)
downloadbcm5719-llvm-410306bf6ed906af77978caa199e5d96376bae66.tar.gz
bcm5719-llvm-410306bf6ed906af77978caa199e5d96376bae66.zip
Add two new AST nodes to represent initialization of an array in terms of
initialization of each array element: * ArrayInitLoopExpr is a prvalue of array type with two subexpressions: a common expression (an OpaqueValueExpr) that represents the up-front computation of the source of the initialization, and a subexpression representing a per-element initializer * ArrayInitIndexExpr is a prvalue of type size_t representing the current position in the loop This will be used to replace the creation of explicit index variables in lambda capture of arrays and copy/move construction of classes with array elements, and also C++17 structured bindings of arrays by value (which inexplicably allow copying an array by value, unlike all of C++'s other array declarations). No uses of these nodes are introduced by this change, however. llvm-svn: 289413
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp80
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp6
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h35
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);
OpenPOWER on IntegriCloud