Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embed improvement #2

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 58 additions & 3 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -4828,16 +4828,15 @@ class PPEmbedExpr final : public Expr {

size_t getDataElementCount(ASTContext &Context) const;

private:
template <bool Const>
class ChildElementIter
: public llvm::iterator_facade_base<
// FIXME: it seems reasonable to make this a random access iterator
// instead, but all current access patterns are a linear walk over
// the contents, so it's being left for follow-up work if needed.
ChildElementIter<Const>, std::input_iterator_tag,
ChildElementIter<Const>, std::random_access_iterator_tag,
std::conditional_t<Const, const IntegerLiteral *,
IntegerLiteral *>> {
IntegerLiteral *>, unsigned> {
Fznamznon marked this conversation as resolved.
Show resolved Hide resolved
friend class PPEmbedExpr;

PPEmbedExpr *PPExpr = nullptr;
Expand Down Expand Up @@ -4875,6 +4874,18 @@ class PPEmbedExpr final : public Expr {
bool operator==(ChildElementIter Other) const {
return (PPExpr == Other.PPExpr && CurOffset == Other.CurOffset);
}
ChildElementIter &operator+=(unsigned N) {
assert(PPExpr && "trying to increment an invalid iterator");
assert(CurOffset != ULLONG_MAX &&
"Already at the end of what we can iterate over");
if (CurOffset + N >= PPExpr->BinaryData->getByteLength()) {
CurOffset = ULLONG_MAX;
PPExpr = nullptr;
} else {
CurOffset += N;
}
return *this;
}
}; // class ChildElementIter

public:
Expand Down Expand Up @@ -4904,10 +4915,54 @@ class PPEmbedExpr final : public Expr {
return T->getStmtClass() == PPEmbedExprClass;
}

ChildElementIter<false> begin() {
return ChildElementIter<false>(this);
}

private:
friend class ASTStmtReader;
};

/// Represent placeholer for a range inside of data imported by #embed
/// directive.
class EmbedSubscriptExpr : public Expr {
PPEmbedExpr *ReferencedEmbed;
unsigned Begin;
unsigned NumOfElements;

public:
explicit EmbedSubscriptExpr(QualType T, PPEmbedExpr *ReferencedEmbed,
unsigned Begin, unsigned NumOfElements)
: Expr(EmbedSubscriptExprClass, T, VK_PRValue, OK_Ordinary),
ReferencedEmbed(ReferencedEmbed), Begin(Begin),
NumOfElements(NumOfElements) {}

static bool classof(const Stmt *T) {
return T->getStmtClass() == EmbedSubscriptExprClass;
}

PPEmbedExpr *getEmbed() const {
return ReferencedEmbed;
}

unsigned getBegin() const {
return Begin;
}

unsigned getDataElementCount() const { return NumOfElements; }

SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); }
SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); }

// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
};

/// Describes an C or C++ initializer list.
///
/// InitListExpr describes an initializer list, which can be used to
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2825,6 +2825,7 @@ DEF_TRAVERSE_STMT(PPEmbedExpr, {
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(IL);
}
})
DEF_TRAVERSE_STMT(EmbedSubscriptExpr, {})

DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/TextNodeDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ class TextNodeDumper
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
void VisitOpenACCConstructStmt(const OpenACCConstructStmt *S);
void VisitEmbedSubscriptExpr(const EmbedSubscriptExpr *S);
};

} // namespace clang
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/StmtNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ def TypoExpr : StmtNode<Expr>;
def RecoveryExpr : StmtNode<Expr>;
def BuiltinBitCastExpr : StmtNode<ExplicitCastExpr>;
def PPEmbedExpr : StmtNode<Expr>;
def EmbedSubscriptExpr : StmtNode<Expr>;

// Microsoft Extensions.
def MSPropertyRefExpr : StmtNode<Expr>;
Expand Down
70 changes: 65 additions & 5 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7708,6 +7708,20 @@ class ExprEvaluatorBase
return true;
}

bool VisitEmbedSubscriptExpr(const EmbedSubscriptExpr *E) {
PPEmbedExpr *PPEmbed = E->getEmbed();
auto It = PPEmbed->begin() + E->getBegin();
const unsigned NumOfEls = E->getDataElementCount();
for (unsigned EmbedIndex = 0; EmbedIndex < NumOfEls; ++EmbedIndex, ++It) {
// This will set Resulting APValue to the last element we see in this
// loop, so this implementation evaluates EmbedSubscriptExpr that refers
// to a single integer out of the box.
if (!StmtVisitorTy::Visit(*It))
return false;
}
return true;
}

bool VisitPredefinedExpr(const PredefinedExpr *E) {
return StmtVisitorTy::Visit(E->getFunctionName());
}
Expand Down Expand Up @@ -11093,11 +11107,26 @@ bool ArrayExprEvaluator::VisitCXXParenListOrInitListExpr(

unsigned NumEltsToInit = Args.size();
unsigned NumElts = CAT->getSize().getZExtValue();
LLVM_DEBUG(llvm::dbgs() << "The number of elements to initialize: "
<< NumEltsToInit << ".\n");
LLVM_DEBUG(llvm::dbgs() << "The number of elements: "
<< NumElts << ".\n");
Fznamznon marked this conversation as resolved.
Show resolved Hide resolved

// If the initializer might depend on the array index, run it for each
// array element.
if (NumEltsToInit != NumElts && MaybeElementDependentArrayFiller(ArrayFiller))
if (NumEltsToInit != NumElts &&
MaybeElementDependentArrayFiller(ArrayFiller)) {
NumEltsToInit = NumElts;
} else {
for (auto *Init : Args) {
if (auto *EmbedS =
dyn_cast<EmbedSubscriptExpr>(Init->IgnoreParenImpCasts())) {
NumEltsToInit += EmbedS->getDataElementCount() - 1;
}
}
if (NumEltsToInit > NumElts)
NumEltsToInit = NumElts;
}

LLVM_DEBUG(llvm::dbgs() << "The number of elements to initialize: "
<< NumEltsToInit << ".\n");
Expand All @@ -11113,18 +11142,49 @@ bool ArrayExprEvaluator::VisitCXXParenListOrInitListExpr(
Result.getArrayFiller() = Filler;
}


LValue Subobject = This;
Subobject.addArray(Info, ExprToVisit, CAT);
for (unsigned Index = 0; Index != NumEltsToInit; ++Index) {
const Expr *Init = Index < Args.size() ? Args[Index] : ArrayFiller;
if (!EvaluateInPlace(Result.getArrayInitializedElt(Index),
Info, Subobject, Init) ||
auto Eval = [&](const Expr *Init, unsigned ArrayIndex, bool EmbedInit) {
LLVM_DEBUG(llvm::dbgs() << "Initializing element : "
<< ArrayIndex << ".\n");
if (!EvaluateInPlace(Result.getArrayInitializedElt(ArrayIndex), Info,
Subobject, Init) ||
!HandleLValueArrayAdjustment(Info, Init, Subobject,
CAT->getElementType(), 1)) {
if (!Info.noteFailure())
return false;
Success = false;
}
if (EmbedInit &&
!Info.Ctx.hasSameType(Init->getType(), CAT->getElementType()))
Result.getArrayInitializedElt(ArrayIndex).getInt() = HandleIntToIntCast(
Info, Init, CAT->getElementType(), Init->getType(),
Result.getArrayInitializedElt(ArrayIndex).getInt());
return true;
};
unsigned ArrayIndex = 0;
for (unsigned Index = 0; Index != NumEltsToInit; ++Index) {
const Expr *Init = Index < Args.size() ? Args[Index] : ArrayFiller;
if (ArrayIndex >= NumEltsToInit)
break;
if (auto *EmbedS =
dyn_cast<EmbedSubscriptExpr>(Init->IgnoreParenImpCasts())) {
PPEmbedExpr *PPEmbed = EmbedS->getEmbed();
auto It = PPEmbed->begin() + EmbedS->getBegin();
const unsigned NumOfEls = EmbedS->getDataElementCount();
for (unsigned EmbedIndex = 0; EmbedIndex < NumOfEls; ++EmbedIndex, ++It) {
Fznamznon marked this conversation as resolved.
Show resolved Hide resolved
if (!Eval(*It, ArrayIndex, true))
return false;
ArrayIndex++;
if (ArrayIndex >= NumEltsToInit)
break;
}
} else {
if (!Eval(Init, ArrayIndex, false))
return false;
ArrayIndex++;
}
}

if (!Result.hasArrayFiller())
Expand Down
29 changes: 26 additions & 3 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -966,9 +966,22 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
if (T->isArrayType()) {
unsigned ElementIndex = 0;
for (const Expr *Init : E->inits()) {
if (!this->visitArrayElemInit(ElementIndex, Init))
return false;
++ElementIndex;
if (auto *EmbedS =
dyn_cast<EmbedSubscriptExpr>(Init->IgnoreParenImpCasts())) {
PPEmbedExpr *PPEmbed = EmbedS->getEmbed();
auto It = PPEmbed->begin() + EmbedS->getBegin();
const unsigned NumOfEls = EmbedS->getDataElementCount();
for (unsigned EmbedIndex = 0; EmbedIndex < NumOfEls;
++EmbedIndex, ++It) {
if (!this->visitArrayElemInit(ElementIndex, *It))
return false;
++ElementIndex;
}
} else {
if (!this->visitArrayElemInit(ElementIndex, Init))
return false;
++ElementIndex;
}
}

// Expand the filler expression.
Expand Down Expand Up @@ -1066,6 +1079,16 @@ bool ByteCodeExprGen<Emitter>::VisitPPEmbedExpr(const PPEmbedExpr *E) {
return true;
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitEmbedSubscriptExpr(
const EmbedSubscriptExpr *E) {
PPEmbedExpr *PPEmbed = E->getEmbed();
auto It = PPEmbed->begin() + E->getBegin();
if (!this->Visit(*It))
return false;
return true;
}

static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,
UnaryExprOrTypeTrait Kind) {
bool AlignOfReturnsPreferred =
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E);
bool VisitPseudoObjectExpr(const PseudoObjectExpr *E);
bool VisitPPEmbedExpr(const PPEmbedExpr *E);
bool VisitEmbedSubscriptExpr(const EmbedSubscriptExpr *E);

protected:
bool visitExpr(const Expr *E) override;
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1161,6 +1161,13 @@ void StmtPrinter::VisitPPEmbedExpr(PPEmbedExpr *Node) {
assert(false && "not yet implemented");
}

void StmtPrinter::VisitEmbedSubscriptExpr(EmbedSubscriptExpr *Node) {
// This isn't yet implemented because the contents of the PPEmbedExpr are
// not generally retained in the AST. e.g., when used as an initializer, the
// expression will be converted into an InitListExpr, etc.
Fznamznon marked this conversation as resolved.
Show resolved Hide resolved
assert(false && "not yet implemented");
}

void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) {
PrintExpr(Node->getSubExpr());
}
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2296,6 +2296,10 @@ void StmtProfiler::VisitSourceLocExpr(const SourceLocExpr *E) {

void StmtProfiler::VisitPPEmbedExpr(const PPEmbedExpr *E) { VisitExpr(E); }

void StmtProfiler::VisitEmbedSubscriptExpr(const EmbedSubscriptExpr *E) {
VisitExpr(E);
}

void StmtProfiler::VisitRecoveryExpr(const RecoveryExpr *E) { VisitExpr(E); }

void StmtProfiler::VisitObjCStringLiteral(const ObjCStringLiteral *S) {
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2673,3 +2673,11 @@ void TextNodeDumper::VisitOpenACCConstructStmt(const OpenACCConstructStmt *S) {
OS << " " << S->getDirectiveKind();
// TODO OpenACC: Dump clauses as well.
}

void TextNodeDumper::VisitEmbedSubscriptExpr(const EmbedSubscriptExpr *S) {
//OS << "begin " << S->getBegin();
//OS << "numofelements " << S->getDataElementCount();
Fznamznon marked this conversation as resolved.
Show resolved Hide resolved
AddChild("begin", [=] { OS << S->getBegin(); });
AddChild("number of elements", [=] { OS << S->getDataElementCount(); });
AddChild("embed", [=] { Visit(S->getEmbed()); });
}
41 changes: 37 additions & 4 deletions clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,17 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
uint64_t NumInitElements = Args.size();

uint64_t NumArrayElements = AType->getNumElements();
for (const auto *Init : Args) {
if (const auto *Embed =
dyn_cast<EmbedSubscriptExpr>(Init->IgnoreParenImpCasts())) {
NumInitElements += Embed->getDataElementCount() - 1;
if (NumInitElements > NumArrayElements) {
NumInitElements = NumArrayElements;
break;
}
}
}

assert(NumInitElements <= NumArrayElements);

QualType elementType =
Expand Down Expand Up @@ -584,10 +595,9 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
// elements have been initialized.
llvm::Value *element = begin;

// Emit the explicit initializers.
for (uint64_t i = 0; i != NumInitElements; ++i) {
auto Emit = [&](Expr *Init, uint64_t ArrayIndex) {
// Advance to the next element.
if (i > 0) {
if (ArrayIndex > 0) {
element = Builder.CreateInBoundsGEP(
llvmElementType, element, one, "arrayinit.element");

Expand All @@ -599,7 +609,30 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,

LValue elementLV = CGF.MakeAddrLValue(
Address(element, llvmElementType, elementAlign), elementType);
EmitInitializationToLValue(Args[i], elementLV);
EmitInitializationToLValue(Init, elementLV);

};

uint64_t ArrayIndex = 0;
// Emit the explicit initializers.
for (uint64_t i = 0; i != NumInitElements; ++i) {
if (ArrayIndex >= NumInitElements)
break;
if (auto *EmbedS =
dyn_cast<EmbedSubscriptExpr>(Args[i]->IgnoreParenImpCasts())) {
PPEmbedExpr *PPEmbed = EmbedS->getEmbed();
auto It = PPEmbed->begin() + EmbedS->getBegin();
const unsigned NumOfEls = EmbedS->getDataElementCount();
for (unsigned EmbedIndex = 0; EmbedIndex < NumOfEls; ++EmbedIndex, ++It) {
Emit(*It, ArrayIndex);
ArrayIndex++;
if (ArrayIndex >= NumInitElements)
break;
}
} else {
Emit(Args[i], ArrayIndex);
ArrayIndex++;
}
}

// Check whether there's a non-trivial array-fill expression.
Expand Down
Loading