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 all 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
97 changes: 92 additions & 5 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -4828,14 +4828,10 @@ 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 *>> {
friend class PPEmbedExpr;
Expand Down Expand Up @@ -4875,6 +4871,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 +4912,89 @@ class PPEmbedExpr final : public Expr {
return T->getStmtClass() == PPEmbedExprClass;
}

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

private:
friend class ASTStmtReader;
};

/// Represents a subrange of data imported by #embed directive. Needed to
/// handle nested initializer lists with #embed directives.
/// Example:
/// struct S {
/// int x, y;
/// };
///
/// struct T {
/// int x[2];
/// struct S s;
/// };
///
/// struct T t[] = {
/// #embed "data" // data contains 10 elements;
/// };
/// The resulting semantic form of initializer list will contain (ESE stands
/// for EmbedSubscriptExpr):
/// { {ESE(first two data elements), {ESE(3rd element), ESE(4th element) }},
/// { {ESE(5th and 6th element), {ESE(7th element), ESE(8th element) }},
/// { {ESE(9th and 10th element), { zeroinitializer }}}
///
/// EmbedSubscriptExpr referencing more than element only appear for arrays of
/// scalars.
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());
}

template <typename Foo, typename... Targs>
bool doForEachDataElement(Foo F, unsigned &StartingIndexInArray,
Targs... Fargs) const {
PPEmbedExpr *PPEmbed = this->getEmbed();
auto It = PPEmbed->begin() + this->getBegin();
const unsigned NumOfEls = this->getDataElementCount();
for (unsigned EmbedIndex = 0; EmbedIndex < NumOfEls; ++EmbedIndex, ++It) {
if (!F(*It, StartingIndexInArray, Fargs...))
return false;
StartingIndexInArray++;
}
return true;
}
};

/// 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
1 change: 1 addition & 0 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3615,6 +3615,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case OpaqueValueExprClass:
case SourceLocExprClass:
case PPEmbedExprClass:
case EmbedSubscriptExprClass:
case ConceptSpecializationExprClass:
case RequiresExprClass:
case SYCLUniqueStableNameExprClass:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ExprClassification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return Cl::CL_PRValue;

case Expr::PPEmbedExprClass:
case Expr::EmbedSubscriptExprClass:
// Nominally, this just goes through as a PRValue until we actually expand
// it and check it.
return Cl::CL_PRValue;
Expand Down
54 changes: 49 additions & 5 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7708,6 +7708,14 @@ class ExprEvaluatorBase
return true;
}

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

bool VisitPredefinedExpr(const PredefinedExpr *E) {
return StmtVisitorTy::Visit(E->getFunctionName());
}
Expand Down Expand Up @@ -11096,8 +11104,19 @@ bool ArrayExprEvaluator::VisitCXXParenListOrInitListExpr(

// 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 +11132,42 @@ 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) {
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;
}
// Type mismatch may happen in case of #embed handling.
if (isa<IntegerLiteral>(Init) &&
!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())) {
if (!EmbedS->doForEachDataElement(Eval, ArrayIndex))
return false;
} else {
if (!Eval(Init, ArrayIndex))
return false;
ArrayIndex++;
}
}

if (!Result.hasArrayFiller())
Expand Down Expand Up @@ -16160,6 +16203,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::GNUNullExprClass:
case Expr::SourceLocExprClass:
case Expr::PPEmbedExprClass:
case Expr::EmbedSubscriptExprClass:
return NoDiag();

case Expr::PackIndexingExprClass:
Expand Down
27 changes: 24 additions & 3 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -964,11 +964,22 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
return this->visitInitList(E->inits(), E);

if (T->isArrayType()) {
auto Eval = [&](Expr *Init, unsigned ElemIndex) {
if (!visitArrayElemInit(ElemIndex, Init))
return false;
return true;
};
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())) {
if (!EmbedS->doForEachDataElement(Eval, ElementIndex))
return false;
} else {
if (!this->visitArrayElemInit(ElementIndex, Init))
return false;
++ElementIndex;
}
}

// Expand the filler expression.
Expand Down Expand Up @@ -1066,6 +1077,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
1 change: 1 addition & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4754,6 +4754,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
case Expr::AtomicExprClass:
case Expr::SourceLocExprClass:
case Expr::PPEmbedExprClass:
case Expr::EmbedSubscriptExprClass:
case Expr::BuiltinBitCastExprClass:
{
NotPrimaryExpr();
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1161,6 +1161,10 @@ void StmtPrinter::VisitPPEmbedExpr(PPEmbedExpr *Node) {
assert(false && "not yet implemented");
}

void StmtPrinter::VisitEmbedSubscriptExpr(EmbedSubscriptExpr *Node) {
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
6 changes: 6 additions & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2673,3 +2673,9 @@ void TextNodeDumper::VisitOpenACCConstructStmt(const OpenACCConstructStmt *S) {
OS << " " << S->getDirectiveKind();
// TODO OpenACC: Dump clauses as well.
}

void TextNodeDumper::VisitEmbedSubscriptExpr(const EmbedSubscriptExpr *S) {
AddChild("begin", [=] { OS << S->getBegin(); });
AddChild("number of elements", [=] { OS << S->getDataElementCount(); });
AddChild("embed", [=] { Visit(S->getEmbed()); });
}
Loading