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

Split off ArgumentShuffleExpr from TupleShuffleExpr #23458

Merged
merged 2 commits into from
Mar 21, 2019
Merged
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
119 changes: 83 additions & 36 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,13 @@ class alignas(8) Expr {

SWIFT_INLINE_BITFIELD_EMPTY(ImplicitConversionExpr, Expr);

SWIFT_INLINE_BITFIELD_FULL(TupleShuffleExpr, ImplicitConversionExpr, 2+16+16+16,
SWIFT_INLINE_BITFIELD_FULL(TupleShuffleExpr, ImplicitConversionExpr, 16,
/// This contains an entry for each element in the Expr type. Each element
/// specifies which index from the SubExpr that the destination element gets.
NumElementMappings : 16
);

SWIFT_INLINE_BITFIELD_FULL(ArgumentShuffleExpr, ImplicitConversionExpr, 2+16+16+16,
TypeImpact : 2,
: NumPadBits,
NumCallerDefaultArgs : 16,
Expand Down Expand Up @@ -2956,22 +2962,56 @@ class UnevaluatedInstanceExpr : public ImplicitConversionExpr {

/// TupleShuffleExpr - This represents a permutation of a tuple value to a new
/// tuple type.
class TupleShuffleExpr final : public ImplicitConversionExpr,
private llvm::TrailingObjects<TupleShuffleExpr, unsigned> {
friend TrailingObjects;

size_t numTrailingObjects(OverloadToken<unsigned>) const {
return Bits.TupleShuffleExpr.NumElementMappings;
}

private:
TupleShuffleExpr(Expr *subExpr, ArrayRef<unsigned> elementMapping,
Type ty)
: ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty) {
Bits.TupleShuffleExpr.NumElementMappings = elementMapping.size();
std::uninitialized_copy(elementMapping.begin(), elementMapping.end(),
getTrailingObjects<unsigned>());
}

public:
static TupleShuffleExpr *create(ASTContext &ctx, Expr *subExpr,
ArrayRef<unsigned> elementMapping,
Type ty);

ArrayRef<unsigned> getElementMapping() const {
return {getTrailingObjects<unsigned>(),
static_cast<size_t>(Bits.TupleShuffleExpr.NumElementMappings)};
}

static bool classof(const Expr *E) {
return E->getKind() == ExprKind::TupleShuffle;
}
};

/// ArgumentShuffleExpr - This represents a "complex" argument list of an
/// ApplyExpr, with default arguments or varargs.
///
/// If hasScalarSource() is true, the subexpression should be treated
/// as if it were implicitly injected into a single-element tuple
/// type. Otherwise, the subexpression is known to have a tuple type.
class TupleShuffleExpr final : public ImplicitConversionExpr,
private llvm::TrailingObjects<TupleShuffleExpr, Expr *, int, unsigned> {
class ArgumentShuffleExpr final : public ImplicitConversionExpr,
private llvm::TrailingObjects<ArgumentShuffleExpr, Expr *, int, unsigned> {
friend TrailingObjects;

size_t numTrailingObjects(OverloadToken<Expr *>) const {
return Bits.TupleShuffleExpr.NumCallerDefaultArgs;
return Bits.ArgumentShuffleExpr.NumCallerDefaultArgs;
}
size_t numTrailingObjects(OverloadToken<int>) const {
return Bits.TupleShuffleExpr.NumElementMappings;
return Bits.ArgumentShuffleExpr.NumElementMappings;
}
size_t numTrailingObjects(OverloadToken<unsigned>) const {
return Bits.TupleShuffleExpr.NumVariadicArgs;
return Bits.ArgumentShuffleExpr.NumVariadicArgs;
}

public:
Expand All @@ -2984,27 +3024,34 @@ class TupleShuffleExpr final : public ImplicitConversionExpr,
/// The element mapping value indicating that the field of the
/// destination tuple should be default-initialized with an expression
/// provided by the caller.
/// FIXME: Yet another indication that TupleShuffleExpr uses the wrong
/// FIXME: Yet another indication that ArgumentShuffleExpr uses the wrong
/// formulation.
CallerDefaultInitialize = -3
};

enum TypeImpact {
/// The source value is a tuple which is destructured and modified to
/// create the result, which is a tuple.
///
/// Example: (x: Int) => (x: Int, y: Int = 0).
TupleToTuple,

/// The source value is a tuple which is destructured and modified to
/// create the result, which is a scalar because it has one element and
/// no labels.
///
/// Example: () -> (_: Int = 0)
/// Another example: (Int, Int) => (_: Int...)
TupleToScalar,

/// The source value is an individual value (possibly one with tuple
/// type) which is inserted into a particular position in the result,
/// which is a tuple.
///
/// Example: (Int) -> (_: Int, y: Int = 0)
ScalarToTuple

// (TupleShuffleExprs are never created for a scalar-to-scalar conversion.)
// (ArgumentShuffleExpr are never created for a scalar-to-scalar conversion.)
};

private:
Expand All @@ -3015,19 +3062,19 @@ class TupleShuffleExpr final : public ImplicitConversionExpr,
/// declaration.
ConcreteDeclRef DefaultArgsOwner;

TupleShuffleExpr(Expr *subExpr, ArrayRef<int> elementMapping,
TypeImpact typeImpact,
ConcreteDeclRef defaultArgsOwner,
ArrayRef<unsigned> VariadicArgs,
Type VarargsArrayTy,
ArrayRef<Expr *> CallerDefaultArgs,
Type ty)
: ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty),
ArgumentShuffleExpr(Expr *subExpr, ArrayRef<int> elementMapping,
TypeImpact typeImpact,
ConcreteDeclRef defaultArgsOwner,
ArrayRef<unsigned> VariadicArgs,
Type VarargsArrayTy,
ArrayRef<Expr *> CallerDefaultArgs,
Type ty)
: ImplicitConversionExpr(ExprKind::ArgumentShuffle, subExpr, ty),
VarargsArrayTy(VarargsArrayTy), DefaultArgsOwner(defaultArgsOwner) {
Bits.TupleShuffleExpr.TypeImpact = typeImpact;
Bits.TupleShuffleExpr.NumCallerDefaultArgs = CallerDefaultArgs.size();
Bits.TupleShuffleExpr.NumElementMappings = elementMapping.size();
Bits.TupleShuffleExpr.NumVariadicArgs = VariadicArgs.size();
Bits.ArgumentShuffleExpr.TypeImpact = typeImpact;
Bits.ArgumentShuffleExpr.NumCallerDefaultArgs = CallerDefaultArgs.size();
Bits.ArgumentShuffleExpr.NumElementMappings = elementMapping.size();
Bits.ArgumentShuffleExpr.NumVariadicArgs = VariadicArgs.size();
std::uninitialized_copy(CallerDefaultArgs.begin(), CallerDefaultArgs.end(),
getTrailingObjects<Expr*>());
std::uninitialized_copy(elementMapping.begin(), elementMapping.end(),
Expand All @@ -3037,23 +3084,23 @@ class TupleShuffleExpr final : public ImplicitConversionExpr,
}

public:
static TupleShuffleExpr *create(ASTContext &ctx, Expr *subExpr,
ArrayRef<int> elementMapping,
TypeImpact typeImpact,
ConcreteDeclRef defaultArgsOwner,
ArrayRef<unsigned> VariadicArgs,
Type VarargsArrayTy,
ArrayRef<Expr *> CallerDefaultArgs,
Type ty);
static ArgumentShuffleExpr *create(ASTContext &ctx, Expr *subExpr,
ArrayRef<int> elementMapping,
TypeImpact typeImpact,
ConcreteDeclRef defaultArgsOwner,
ArrayRef<unsigned> VariadicArgs,
Type VarargsArrayTy,
ArrayRef<Expr *> CallerDefaultArgs,
Type ty);

ArrayRef<int> getElementMapping() const {
return {getTrailingObjects<int>(),
static_cast<size_t>(Bits.TupleShuffleExpr.NumElementMappings)};
static_cast<size_t>(Bits.ArgumentShuffleExpr.NumElementMappings)};
}

/// What is the type impact of this shuffle?
TypeImpact getTypeImpact() const {
return TypeImpact(Bits.TupleShuffleExpr.TypeImpact);
return TypeImpact(Bits.ArgumentShuffleExpr.TypeImpact);
}

bool isSourceScalar() const {
Expand All @@ -3075,7 +3122,7 @@ class TupleShuffleExpr final : public ImplicitConversionExpr,
/// Retrieve the argument indices for the variadic arguments.
ArrayRef<unsigned> getVariadicArgs() const {
return {getTrailingObjects<unsigned>(),
static_cast<size_t>(Bits.TupleShuffleExpr.NumVariadicArgs)};
static_cast<size_t>(Bits.ArgumentShuffleExpr.NumVariadicArgs)};
}

/// Retrieve the owner of the default arguments.
Expand All @@ -3084,17 +3131,17 @@ class TupleShuffleExpr final : public ImplicitConversionExpr,
/// Retrieve the caller-defaulted arguments.
ArrayRef<Expr *> getCallerDefaultArgs() const {
return {getTrailingObjects<Expr*>(),
static_cast<size_t>(Bits.TupleShuffleExpr.NumCallerDefaultArgs)};
static_cast<size_t>(Bits.ArgumentShuffleExpr.NumCallerDefaultArgs)};
}

/// Retrieve the caller-defaulted arguments.
MutableArrayRef<Expr *> getCallerDefaultArgs() {
return {getTrailingObjects<Expr*>(),
static_cast<size_t>(Bits.TupleShuffleExpr.NumCallerDefaultArgs)};
static_cast<size_t>(Bits.ArgumentShuffleExpr.NumCallerDefaultArgs)};
}

static bool classof(const Expr *E) {
return E->getKind() == ExprKind::TupleShuffle;
return E->getKind() == ExprKind::ArgumentShuffle;
}
};

Expand Down Expand Up @@ -3975,7 +4022,7 @@ class ApplyExpr : public Expr {

/// Returns true if \c e could be used as the call's argument. For most \c ApplyExpr
/// subclasses, this means it is a \c ParenExpr, \c TupleExpr, or
/// \c TupleShuffleExpr.
/// \c ArgumentShuffleExpr.
bool validateArg(Expr *e) const;

protected:
Expand Down Expand Up @@ -5355,7 +5402,7 @@ inline bool ApplyExpr::validateArg(Expr *e) const {
else if (isa<BinaryExpr>(this))
return isa<TupleExpr>(e);
else
return isa<ParenExpr>(e) || isa<TupleExpr>(e) || isa<TupleShuffleExpr>(e);
return isa<ParenExpr>(e) || isa<TupleExpr>(e) || isa<ArgumentShuffleExpr>(e);
}

inline Expr *const *CollectionExpr::getTrailingObjectsPointer() const {
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/ExprNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ ABSTRACT_EXPR(Apply, Expr)
ABSTRACT_EXPR(ImplicitConversion, Expr)
EXPR(Load, ImplicitConversionExpr)
EXPR(TupleShuffle, ImplicitConversionExpr)
EXPR(ArgumentShuffle, ImplicitConversionExpr)
EXPR(UnresolvedTypeConversion, ImplicitConversionExpr)
EXPR(FunctionConversion, ImplicitConversionExpr)
EXPR(CovariantFunctionConversion, ImplicitConversionExpr)
Expand Down
17 changes: 14 additions & 3 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2118,15 +2118,26 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
void visitTupleShuffleExpr(TupleShuffleExpr *E) {
printCommon(E, "tuple_shuffle_expr");
OS << " elements=[";
for (unsigned i = 0, e = E->getElementMapping().size(); i != e; ++i) {
if (i) OS << ", ";
OS << E->getElementMapping()[i];
}
OS << "]\n";
printRec(E->getSubExpr());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
void visitArgumentShuffleExpr(ArgumentShuffleExpr *E) {
printCommon(E, "tuple_shuffle_expr");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to also update this to argument_shuffle_expr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I grepped for TupleShuffleExpr but forgot to check other spellings. I'll fix this in a follow-up PR.

switch (E->getTypeImpact()) {
case TupleShuffleExpr::ScalarToTuple:
case ArgumentShuffleExpr::ScalarToTuple:
OS << " scalar_to_tuple";
break;
case TupleShuffleExpr::TupleToTuple:
case ArgumentShuffleExpr::TupleToTuple:
OS << " tuple_to_tuple";
break;
case TupleShuffleExpr::TupleToScalar:
case ArgumentShuffleExpr::TupleToScalar:
OS << " tuple_to_scalar";
break;
}
Expand Down
42 changes: 33 additions & 9 deletions lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1709,10 +1709,10 @@ class Verifier : public ASTWalker {
}
};

// If we have a tuple_shuffle, strip it off. We want to visit the
// If we have an argument shuffle, strip it off. We want to visit the
// underlying paren or tuple expr.
if (auto *TupleShuffle = dyn_cast<TupleShuffleExpr>(Arg)) {
Arg = TupleShuffle->getSubExpr();
if (auto *ArgShuffle = dyn_cast<ArgumentShuffleExpr>(Arg)) {
Arg = ArgShuffle->getSubExpr();
}

if (auto *ParentExprArg = dyn_cast<ParenExpr>(Arg)) {
Expand Down Expand Up @@ -1991,6 +1991,30 @@ class Verifier : public ASTWalker {
void verifyChecked(TupleShuffleExpr *E) {
PrettyStackTraceExpr debugStack(Ctx, "verifying TupleShuffleExpr", E);

auto getSubElementType = [&](unsigned i) {
return (E->getSubExpr()->getType()->castTo<TupleType>()
->getElementType(i));
};

/// Retrieve the ith element type from the resulting tuple type.
auto getOuterElementType = [&](unsigned i) -> Type {
return E->getType()->castTo<TupleType>()->getElementType(i);
};

for (unsigned i = 0, e = E->getElementMapping().size(); i != e; ++i) {
int subElem = E->getElementMapping()[i];
if (!getOuterElementType(i)->isEqual(getSubElementType(subElem))) {
Out << "Type mismatch in TupleShuffleExpr\n";
abort();
}
}

verifyCheckedBase(E);
}

void verifyChecked(ArgumentShuffleExpr *E) {
PrettyStackTraceExpr debugStack(Ctx, "verifying ArgumentShuffleExpr", E);

auto getSubElementType = [&](unsigned i) {
if (E->isSourceScalar()) {
assert(i == 0);
Expand All @@ -2015,30 +2039,30 @@ class Verifier : public ASTWalker {
unsigned callerDefaultArgIndex = 0;
for (unsigned i = 0, e = E->getElementMapping().size(); i != e; ++i) {
int subElem = E->getElementMapping()[i];
if (subElem == TupleShuffleExpr::DefaultInitialize)
if (subElem == ArgumentShuffleExpr::DefaultInitialize)
continue;
if (subElem == TupleShuffleExpr::Variadic) {
if (subElem == ArgumentShuffleExpr::Variadic) {
varargsType = (E->getType()->castTo<TupleType>()
->getElement(i).getVarargBaseTy());
break;
}
if (subElem == TupleShuffleExpr::CallerDefaultInitialize) {
if (subElem == ArgumentShuffleExpr::CallerDefaultInitialize) {
auto init = E->getCallerDefaultArgs()[callerDefaultArgIndex++];
if (!getOuterElementType(i)->isEqual(init->getType())) {
Out << "Type mismatch in TupleShuffleExpr\n";
Out << "Type mismatch in ArgumentShuffleExpr\n";
abort();
}
continue;
}
if (!getOuterElementType(i)->isEqual(getSubElementType(subElem))) {
Out << "Type mismatch in TupleShuffleExpr\n";
Out << "Type mismatch in ArgumentShuffleExpr\n";
abort();
}
}
if (varargsType) {
for (auto sourceIdx : E->getVariadicArgs()) {
if (!getSubElementType(sourceIdx)->isEqual(varargsType)) {
Out << "Vararg type mismatch in TupleShuffleExpr\n";
Out << "Vararg type mismatch in ArgumentShuffleExpr\n";
abort();
}
}
Expand Down
10 changes: 10 additions & 0 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,16 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
return nullptr;
}

return E;
}

Expr *visitArgumentShuffleExpr(ArgumentShuffleExpr *E) {
if (Expr *E2 = doIt(E->getSubExpr())) {
E->setSubExpr(E2);
} else {
return nullptr;
}

for (auto &defaultArg : E->getCallerDefaultArgs()) {
if (Expr *newDefaultArg = doIt(defaultArg))
defaultArg = newDefaultArg;
Expand Down
Loading