Skip to content

Commit

Permalink
AST: Remove argument list-specific parts of TupleShuffleExpr
Browse files Browse the repository at this point in the history
Before extending TupleShuffleExpr to represent all tuple
conversions allowed by the constraint solver, remove the
parts of TupleShuffleExpr that are no longer needed; this is
support for default arguments, varargs, and scalar-to-tuple and
tuple-to-scalar conversions.
  • Loading branch information
slavapestov committed Mar 21, 2019
1 parent d470e9d commit 428c709
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 253 deletions.
135 changes: 9 additions & 126 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,17 +290,10 @@ class alignas(8) Expr {

SWIFT_INLINE_BITFIELD_EMPTY(ImplicitConversionExpr, Expr);

SWIFT_INLINE_BITFIELD_FULL(TupleShuffleExpr, ImplicitConversionExpr, 2+16+16+16,
TypeImpact : 2,
: NumPadBits,
NumCallerDefaultArgs : 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.
/// If the element value is DefaultInitialize, then the destination value
/// gets the default initializer for that tuple element value.
NumElementMappings : 16,
/// The arguments that are packed into the variadic element.
NumVariadicArgs : 16
NumElementMappings : 16
);

SWIFT_INLINE_BITFIELD_FULL(ArgumentShuffleExpr, ImplicitConversionExpr, 2+16+16+16,
Expand Down Expand Up @@ -2969,141 +2962,31 @@ class UnevaluatedInstanceExpr : public ImplicitConversionExpr {

/// TupleShuffleExpr - This represents a permutation of a tuple value to a new
/// tuple type.
///
/// 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> {
private llvm::TrailingObjects<TupleShuffleExpr, unsigned> {
friend TrailingObjects;

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

public:
enum : int {
/// The element mapping value indicating that a field of the destination
/// tuple should be default-initialized.
DefaultInitialize = -1,
/// The element mapping is part of the variadic field.
Variadic = -2,
/// 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
/// formulation.
CallerDefaultInitialize = -3
};

enum TypeImpact {
/// The source value is a tuple which is destructured and modified to
/// create the result, which is a tuple.
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.
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.
ScalarToTuple

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

private:
/// If we're doing a varargs shuffle, this is the array type to build.
Type VarargsArrayTy;

/// If there are any default arguments, the owning function
/// declaration.
ConcreteDeclRef DefaultArgsOwner;

TupleShuffleExpr(Expr *subExpr, ArrayRef<int> elementMapping,
TypeImpact typeImpact,
ConcreteDeclRef defaultArgsOwner,
ArrayRef<unsigned> VariadicArgs,
Type VarargsArrayTy,
ArrayRef<Expr *> CallerDefaultArgs,
TupleShuffleExpr(Expr *subExpr, ArrayRef<unsigned> elementMapping,
Type ty)
: ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty),
VarargsArrayTy(VarargsArrayTy), DefaultArgsOwner(defaultArgsOwner) {
Bits.TupleShuffleExpr.TypeImpact = typeImpact;
Bits.TupleShuffleExpr.NumCallerDefaultArgs = CallerDefaultArgs.size();
: ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty) {
Bits.TupleShuffleExpr.NumElementMappings = elementMapping.size();
Bits.TupleShuffleExpr.NumVariadicArgs = VariadicArgs.size();
std::uninitialized_copy(CallerDefaultArgs.begin(), CallerDefaultArgs.end(),
getTrailingObjects<Expr*>());
std::uninitialized_copy(elementMapping.begin(), elementMapping.end(),
getTrailingObjects<int>());
std::uninitialized_copy(VariadicArgs.begin(), VariadicArgs.end(),
getTrailingObjects<unsigned>());
}

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

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

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

bool isSourceScalar() const {
return getTypeImpact() == ScalarToTuple;
}

bool isResultScalar() const {
return getTypeImpact() == TupleToScalar;
}

Type getVarargsArrayType() const {
assert(!VarargsArrayTy.isNull());
return VarargsArrayTy;
}
Type getVarargsArrayTypeOrNull() const {
return VarargsArrayTy;
}

/// Retrieve the argument indices for the variadic arguments.
ArrayRef<unsigned> getVariadicArgs() const {
ArrayRef<unsigned> getElementMapping() const {
return {getTrailingObjects<unsigned>(),
static_cast<size_t>(Bits.TupleShuffleExpr.NumVariadicArgs)};
}

/// Retrieve the owner of the default arguments.
ConcreteDeclRef getDefaultArgsOwner() const { return DefaultArgsOwner; }

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

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

static bool classof(const Expr *E) {
Expand Down
27 changes: 1 addition & 26 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2119,37 +2119,12 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
}
void visitTupleShuffleExpr(TupleShuffleExpr *E) {
printCommon(E, "tuple_shuffle_expr");
switch (E->getTypeImpact()) {
case TupleShuffleExpr::ScalarToTuple:
OS << " scalar_to_tuple";
break;
case TupleShuffleExpr::TupleToTuple:
OS << " tuple_to_tuple";
break;
case TupleShuffleExpr::TupleToScalar:
OS << " tuple_to_scalar";
break;
}
OS << " elements=[";
for (unsigned i = 0, e = E->getElementMapping().size(); i != e; ++i) {
if (i) OS << ", ";
OS << E->getElementMapping()[i];
}
OS << "]";
OS << " variadic_sources=[";
interleave(E->getVariadicArgs(),
[&](unsigned source) {
OS << source;
},
[&] { OS << ", "; });
OS << "]";

if (auto defaultArgsOwner = E->getDefaultArgsOwner()) {
OS << " default_args_owner=";
defaultArgsOwner.dump(OS);
}

OS << "\n";
OS << "]\n";
printRec(E->getSubExpr());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
Expand Down
41 changes: 3 additions & 38 deletions lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1992,57 +1992,22 @@ class Verifier : public ASTWalker {
PrettyStackTraceExpr debugStack(Ctx, "verifying TupleShuffleExpr", E);

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

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

Type varargsType;
unsigned callerDefaultArgIndex = 0;
for (unsigned i = 0, e = E->getElementMapping().size(); i != e; ++i) {
int subElem = E->getElementMapping()[i];
if (subElem == TupleShuffleExpr::DefaultInitialize)
continue;
if (subElem == TupleShuffleExpr::Variadic) {
varargsType = (E->getType()->castTo<TupleType>()
->getElement(i).getVarargBaseTy());
break;
}
if (subElem == TupleShuffleExpr::CallerDefaultInitialize) {
auto init = E->getCallerDefaultArgs()[callerDefaultArgIndex++];
if (!getOuterElementType(i)->isEqual(init->getType())) {
Out << "Type mismatch in TupleShuffleExpr\n";
abort();
}
continue;
}
if (!getOuterElementType(i)->isEqual(getSubElementType(subElem))) {
Out << "Type mismatch in TupleShuffleExpr\n";
abort();
}
}
if (varargsType) {
for (auto sourceIdx : E->getVariadicArgs()) {
if (!getSubElementType(sourceIdx)->isEqual(varargsType)) {
Out << "Vararg type mismatch in TupleShuffleExpr\n";
abort();
}
}
}

verifyCheckedBase(E);
}
Expand Down
7 changes: 0 additions & 7 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,13 +646,6 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
return nullptr;
}

for (auto &defaultArg : E->getCallerDefaultArgs()) {
if (Expr *newDefaultArg = doIt(defaultArg))
defaultArg = newDefaultArg;
else
return nullptr;
}

return E;
}

Expand Down
15 changes: 3 additions & 12 deletions lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1335,20 +1335,11 @@ CaptureListExpr *CaptureListExpr::create(ASTContext &ctx,

TupleShuffleExpr *TupleShuffleExpr::create(ASTContext &ctx,
Expr *subExpr,
ArrayRef<int> elementMapping,
TypeImpact typeImpact,
ConcreteDeclRef defaultArgsOwner,
ArrayRef<unsigned> VariadicArgs,
Type VarargsArrayTy,
ArrayRef<Expr *> CallerDefaultArgs,
ArrayRef<unsigned> elementMapping,
Type ty) {
auto size = totalSizeToAlloc<Expr*, int, unsigned>(CallerDefaultArgs.size(),
elementMapping.size(),
VariadicArgs.size());
auto size = totalSizeToAlloc<unsigned>(elementMapping.size());
auto mem = ctx.Allocate(size, alignof(TupleShuffleExpr));
return ::new(mem) TupleShuffleExpr(subExpr, elementMapping, typeImpact,
defaultArgsOwner, VariadicArgs,
VarargsArrayTy, CallerDefaultArgs, ty);
return ::new(mem) TupleShuffleExpr(subExpr, elementMapping, ty);
}

ArgumentShuffleExpr *ArgumentShuffleExpr::create(ASTContext &ctx,
Expand Down
37 changes: 7 additions & 30 deletions lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2289,19 +2289,14 @@ static void emitTupleShuffleExprInto(RValueEmitter &emitter,
// Map outer initializations into a tuple of inner initializations:
// - fill out the initialization elements with null
TupleInitialization innerTupleInit;
if (E->isSourceScalar()) {
innerTupleInit.SubInitializations.push_back(nullptr);
} else {
CanTupleType innerTuple =
cast<TupleType>(E->getSubExpr()->getType()->getCanonicalType());
innerTupleInit.SubInitializations.resize(innerTuple->getNumElements());
}

CanTupleType innerTuple =
cast<TupleType>(E->getSubExpr()->getType()->getCanonicalType());
innerTupleInit.SubInitializations.resize(innerTuple->getNumElements());

// Map all the outer initializations to their appropriate targets.
for (unsigned outerIndex = 0; outerIndex != outerInits.size(); outerIndex++) {
auto innerMapping = E->getElementMapping()[outerIndex];
assert(innerMapping >= 0 &&
"non-argument tuple shuffle with default arguments or variadics?");
innerTupleInit.SubInitializations[innerMapping] =
std::move(outerInits[outerIndex]);
}
Expand All @@ -2313,22 +2308,13 @@ static void emitTupleShuffleExprInto(RValueEmitter &emitter,
#endif

// Emit the sub-expression into the tuple initialization we just built.
if (E->isSourceScalar()) {
emitter.SGF.emitExprInto(E->getSubExpr(),
innerTupleInit.SubInitializations[0].get());
} else {
emitter.SGF.emitExprInto(E->getSubExpr(), &innerTupleInit);
}
emitter.SGF.emitExprInto(E->getSubExpr(), &innerTupleInit);

outerTupleInit->finishInitialization(emitter.SGF);
}

RValue RValueEmitter::visitTupleShuffleExpr(TupleShuffleExpr *E,
SGFContext C) {
// FIXME: Once we're no longer using this code path for enum element payloads,
// also assert that !E->isSourceScalar().
assert(!E->isResultScalar());

// If we're emitting into an initialization, we can try shuffling the
// elements of the initialization.
if (Initialization *I = C.getEmitInto()) {
Expand All @@ -2340,12 +2326,8 @@ RValue RValueEmitter::visitTupleShuffleExpr(TupleShuffleExpr *E,

// Emit the sub-expression tuple and destructure it into elements.
SmallVector<RValue, 4> elements;
if (E->isSourceScalar()) {
elements.push_back(visit(E->getSubExpr()));
} else {
visit(E->getSubExpr()).extractElements(elements);
}

visit(E->getSubExpr()).extractElements(elements);

// Prepare a new tuple to hold the shuffled result.
RValue result(E->getType()->getCanonicalType());

Expand All @@ -2359,11 +2341,6 @@ RValue RValueEmitter::visitTupleShuffleExpr(TupleShuffleExpr *E,
"ran out of shuffle indexes before running out of fields?!");
int shuffleIndex = *shuffleIndexIterator++;

assert(shuffleIndex != TupleShuffleExpr::DefaultInitialize &&
shuffleIndex != TupleShuffleExpr::CallerDefaultInitialize &&
shuffleIndex != TupleShuffleExpr::Variadic &&
"Only argument tuples can have default initializers & varargs");

// Map from a different tuple element.
result.addElement(
std::move(elements[shuffleIndex]).ensurePlusOne(SGF, E));
Expand Down
Loading

0 comments on commit 428c709

Please sign in to comment.