Skip to content

Commit d470e9d

Browse files
committed
AST: Split off ArgumentShuffleExpr from TupleShuffleExpr
Right now we use TupleShuffleExpr for two completely different things: - Tuple conversions, where elements can be re-ordered and labels can be introduced/eliminated - Complex argument lists, involving default arguments or varargs The first case does not allow default arguments or varargs, and the second case does not allow re-ordering or introduction/elimination of labels. Furthermore, the first case has a representation limitation that prevents us from expressing tuple conversions that change the type of tuple elements. For all these reasons, it is better if we use two separate Expr kinds for these purposes. For now, just make an identical copy of TupleShuffleExpr and call it ArgumentShuffleExpr. In CSApply, use ArgumentShuffleExpr when forming the arguments to a call, and keep using TupleShuffleExpr for tuple conversions. Each usage of TupleShuffleExpr has been audited to see if it should instead look at ArgumentShuffleExpr. In sequent commits I plan on redesigning TupleShuffleExpr to correctly represent all tuple conversions without any unnecessary baggage. Longer term, we actually want to change the representation of CallExpr to directly store an argument list; then instead of a single child expression that must be a ParenExpr, TupleExpr or ArgumentShuffleExpr, all CallExprs will have a uniform representation and ArgumentShuffleExpr will go away altogether. This should reduce memory usage and radically simplify parts of SILGen.
1 parent 8fcd4e6 commit d470e9d

19 files changed

+391
-102
lines changed

include/swift/AST/Expr.h

Lines changed: 166 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,19 @@ class alignas(8) Expr {
303303
NumVariadicArgs : 16
304304
);
305305

306+
SWIFT_INLINE_BITFIELD_FULL(ArgumentShuffleExpr, ImplicitConversionExpr, 2+16+16+16,
307+
TypeImpact : 2,
308+
: NumPadBits,
309+
NumCallerDefaultArgs : 16,
310+
/// This contains an entry for each element in the Expr type. Each element
311+
/// specifies which index from the SubExpr that the destination element gets.
312+
/// If the element value is DefaultInitialize, then the destination value
313+
/// gets the default initializer for that tuple element value.
314+
NumElementMappings : 16,
315+
/// The arguments that are packed into the variadic element.
316+
NumVariadicArgs : 16
317+
);
318+
306319
SWIFT_INLINE_BITFIELD(ForceValueExpr, Expr, 1,
307320
ForcedIUO : 1
308321
);
@@ -3098,6 +3111,157 @@ class TupleShuffleExpr final : public ImplicitConversionExpr,
30983111
}
30993112
};
31003113

3114+
/// ArgumentShuffleExpr - This represents a "complex" argument list of an
3115+
/// ApplyExpr, with default arguments or varargs.
3116+
///
3117+
/// If hasScalarSource() is true, the subexpression should be treated
3118+
/// as if it were implicitly injected into a single-element tuple
3119+
/// type. Otherwise, the subexpression is known to have a tuple type.
3120+
class ArgumentShuffleExpr final : public ImplicitConversionExpr,
3121+
private llvm::TrailingObjects<ArgumentShuffleExpr, Expr *, int, unsigned> {
3122+
friend TrailingObjects;
3123+
3124+
size_t numTrailingObjects(OverloadToken<Expr *>) const {
3125+
return Bits.ArgumentShuffleExpr.NumCallerDefaultArgs;
3126+
}
3127+
size_t numTrailingObjects(OverloadToken<int>) const {
3128+
return Bits.ArgumentShuffleExpr.NumElementMappings;
3129+
}
3130+
size_t numTrailingObjects(OverloadToken<unsigned>) const {
3131+
return Bits.ArgumentShuffleExpr.NumVariadicArgs;
3132+
}
3133+
3134+
public:
3135+
enum : int {
3136+
/// The element mapping value indicating that a field of the destination
3137+
/// tuple should be default-initialized.
3138+
DefaultInitialize = -1,
3139+
/// The element mapping is part of the variadic field.
3140+
Variadic = -2,
3141+
/// The element mapping value indicating that the field of the
3142+
/// destination tuple should be default-initialized with an expression
3143+
/// provided by the caller.
3144+
/// FIXME: Yet another indication that ArgumentShuffleExpr uses the wrong
3145+
/// formulation.
3146+
CallerDefaultInitialize = -3
3147+
};
3148+
3149+
enum TypeImpact {
3150+
/// The source value is a tuple which is destructured and modified to
3151+
/// create the result, which is a tuple.
3152+
///
3153+
/// Example: (x: Int) => (x: Int, y: Int = 0).
3154+
TupleToTuple,
3155+
3156+
/// The source value is a tuple which is destructured and modified to
3157+
/// create the result, which is a scalar because it has one element and
3158+
/// no labels.
3159+
///
3160+
/// Example: () -> (_: Int = 0)
3161+
/// Another example: (Int, Int) => (_: Int...)
3162+
TupleToScalar,
3163+
3164+
/// The source value is an individual value (possibly one with tuple
3165+
/// type) which is inserted into a particular position in the result,
3166+
/// which is a tuple.
3167+
///
3168+
/// Example: (Int) -> (_: Int, y: Int = 0)
3169+
ScalarToTuple
3170+
3171+
// (ArgumentShuffleExpr are never created for a scalar-to-scalar conversion.)
3172+
};
3173+
3174+
private:
3175+
/// If we're doing a varargs shuffle, this is the array type to build.
3176+
Type VarargsArrayTy;
3177+
3178+
/// If there are any default arguments, the owning function
3179+
/// declaration.
3180+
ConcreteDeclRef DefaultArgsOwner;
3181+
3182+
ArgumentShuffleExpr(Expr *subExpr, ArrayRef<int> elementMapping,
3183+
TypeImpact typeImpact,
3184+
ConcreteDeclRef defaultArgsOwner,
3185+
ArrayRef<unsigned> VariadicArgs,
3186+
Type VarargsArrayTy,
3187+
ArrayRef<Expr *> CallerDefaultArgs,
3188+
Type ty)
3189+
: ImplicitConversionExpr(ExprKind::ArgumentShuffle, subExpr, ty),
3190+
VarargsArrayTy(VarargsArrayTy), DefaultArgsOwner(defaultArgsOwner) {
3191+
Bits.ArgumentShuffleExpr.TypeImpact = typeImpact;
3192+
Bits.ArgumentShuffleExpr.NumCallerDefaultArgs = CallerDefaultArgs.size();
3193+
Bits.ArgumentShuffleExpr.NumElementMappings = elementMapping.size();
3194+
Bits.ArgumentShuffleExpr.NumVariadicArgs = VariadicArgs.size();
3195+
std::uninitialized_copy(CallerDefaultArgs.begin(), CallerDefaultArgs.end(),
3196+
getTrailingObjects<Expr*>());
3197+
std::uninitialized_copy(elementMapping.begin(), elementMapping.end(),
3198+
getTrailingObjects<int>());
3199+
std::uninitialized_copy(VariadicArgs.begin(), VariadicArgs.end(),
3200+
getTrailingObjects<unsigned>());
3201+
}
3202+
3203+
public:
3204+
static ArgumentShuffleExpr *create(ASTContext &ctx, Expr *subExpr,
3205+
ArrayRef<int> elementMapping,
3206+
TypeImpact typeImpact,
3207+
ConcreteDeclRef defaultArgsOwner,
3208+
ArrayRef<unsigned> VariadicArgs,
3209+
Type VarargsArrayTy,
3210+
ArrayRef<Expr *> CallerDefaultArgs,
3211+
Type ty);
3212+
3213+
ArrayRef<int> getElementMapping() const {
3214+
return {getTrailingObjects<int>(),
3215+
static_cast<size_t>(Bits.ArgumentShuffleExpr.NumElementMappings)};
3216+
}
3217+
3218+
/// What is the type impact of this shuffle?
3219+
TypeImpact getTypeImpact() const {
3220+
return TypeImpact(Bits.ArgumentShuffleExpr.TypeImpact);
3221+
}
3222+
3223+
bool isSourceScalar() const {
3224+
return getTypeImpact() == ScalarToTuple;
3225+
}
3226+
3227+
bool isResultScalar() const {
3228+
return getTypeImpact() == TupleToScalar;
3229+
}
3230+
3231+
Type getVarargsArrayType() const {
3232+
assert(!VarargsArrayTy.isNull());
3233+
return VarargsArrayTy;
3234+
}
3235+
Type getVarargsArrayTypeOrNull() const {
3236+
return VarargsArrayTy;
3237+
}
3238+
3239+
/// Retrieve the argument indices for the variadic arguments.
3240+
ArrayRef<unsigned> getVariadicArgs() const {
3241+
return {getTrailingObjects<unsigned>(),
3242+
static_cast<size_t>(Bits.ArgumentShuffleExpr.NumVariadicArgs)};
3243+
}
3244+
3245+
/// Retrieve the owner of the default arguments.
3246+
ConcreteDeclRef getDefaultArgsOwner() const { return DefaultArgsOwner; }
3247+
3248+
/// Retrieve the caller-defaulted arguments.
3249+
ArrayRef<Expr *> getCallerDefaultArgs() const {
3250+
return {getTrailingObjects<Expr*>(),
3251+
static_cast<size_t>(Bits.ArgumentShuffleExpr.NumCallerDefaultArgs)};
3252+
}
3253+
3254+
/// Retrieve the caller-defaulted arguments.
3255+
MutableArrayRef<Expr *> getCallerDefaultArgs() {
3256+
return {getTrailingObjects<Expr*>(),
3257+
static_cast<size_t>(Bits.ArgumentShuffleExpr.NumCallerDefaultArgs)};
3258+
}
3259+
3260+
static bool classof(const Expr *E) {
3261+
return E->getKind() == ExprKind::ArgumentShuffle;
3262+
}
3263+
};
3264+
31013265
/// LoadExpr - Turn an l-value into an r-value by performing a "load"
31023266
/// operation. This operation may actually be a logical operation,
31033267
/// i.e. one implemented using a call to a potentially user-defined
@@ -3975,7 +4139,7 @@ class ApplyExpr : public Expr {
39754139

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

39814145
protected:
@@ -5355,7 +5519,7 @@ inline bool ApplyExpr::validateArg(Expr *e) const {
53555519
else if (isa<BinaryExpr>(this))
53565520
return isa<TupleExpr>(e);
53575521
else
5358-
return isa<ParenExpr>(e) || isa<TupleExpr>(e) || isa<TupleShuffleExpr>(e);
5522+
return isa<ParenExpr>(e) || isa<TupleExpr>(e) || isa<ArgumentShuffleExpr>(e);
53595523
}
53605524

53615525
inline Expr *const *CollectionExpr::getTrailingObjectsPointer() const {

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ ABSTRACT_EXPR(Apply, Expr)
144144
ABSTRACT_EXPR(ImplicitConversion, Expr)
145145
EXPR(Load, ImplicitConversionExpr)
146146
EXPR(TupleShuffle, ImplicitConversionExpr)
147+
EXPR(ArgumentShuffle, ImplicitConversionExpr)
147148
EXPR(UnresolvedTypeConversion, ImplicitConversionExpr)
148149
EXPR(FunctionConversion, ImplicitConversionExpr)
149150
EXPR(CovariantFunctionConversion, ImplicitConversionExpr)

lib/AST/ASTDumper.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,6 +2153,42 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
21532153
printRec(E->getSubExpr());
21542154
PrintWithColorRAII(OS, ParenthesisColor) << ')';
21552155
}
2156+
void visitArgumentShuffleExpr(ArgumentShuffleExpr *E) {
2157+
printCommon(E, "tuple_shuffle_expr");
2158+
switch (E->getTypeImpact()) {
2159+
case ArgumentShuffleExpr::ScalarToTuple:
2160+
OS << " scalar_to_tuple";
2161+
break;
2162+
case ArgumentShuffleExpr::TupleToTuple:
2163+
OS << " tuple_to_tuple";
2164+
break;
2165+
case ArgumentShuffleExpr::TupleToScalar:
2166+
OS << " tuple_to_scalar";
2167+
break;
2168+
}
2169+
OS << " elements=[";
2170+
for (unsigned i = 0, e = E->getElementMapping().size(); i != e; ++i) {
2171+
if (i) OS << ", ";
2172+
OS << E->getElementMapping()[i];
2173+
}
2174+
OS << "]";
2175+
OS << " variadic_sources=[";
2176+
interleave(E->getVariadicArgs(),
2177+
[&](unsigned source) {
2178+
OS << source;
2179+
},
2180+
[&] { OS << ", "; });
2181+
OS << "]";
2182+
2183+
if (auto defaultArgsOwner = E->getDefaultArgsOwner()) {
2184+
OS << " default_args_owner=";
2185+
defaultArgsOwner.dump(OS);
2186+
}
2187+
2188+
OS << "\n";
2189+
printRec(E->getSubExpr());
2190+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2191+
}
21562192
void visitUnresolvedTypeConversionExpr(UnresolvedTypeConversionExpr *E) {
21572193
printCommon(E, "unresolvedtype_conversion_expr") << '\n';
21582194
printRec(E->getSubExpr());

lib/AST/ASTVerifier.cpp

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,10 +1709,10 @@ class Verifier : public ASTWalker {
17091709
}
17101710
};
17111711

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

17181718
if (auto *ParentExprArg = dyn_cast<ParenExpr>(Arg)) {
@@ -2047,6 +2047,65 @@ class Verifier : public ASTWalker {
20472047
verifyCheckedBase(E);
20482048
}
20492049

2050+
void verifyChecked(ArgumentShuffleExpr *E) {
2051+
PrettyStackTraceExpr debugStack(Ctx, "verifying ArgumentShuffleExpr", E);
2052+
2053+
auto getSubElementType = [&](unsigned i) {
2054+
if (E->isSourceScalar()) {
2055+
assert(i == 0);
2056+
return E->getSubExpr()->getType();
2057+
} else {
2058+
return (E->getSubExpr()->getType()->castTo<TupleType>()
2059+
->getElementType(i));
2060+
}
2061+
};
2062+
2063+
/// Retrieve the ith element type from the resulting tuple type.
2064+
auto getOuterElementType = [&](unsigned i) -> Type {
2065+
if (E->isResultScalar()) {
2066+
assert(i == 0);
2067+
return E->getType()->getWithoutParens();
2068+
} else {
2069+
return E->getType()->castTo<TupleType>()->getElementType(i);
2070+
}
2071+
};
2072+
2073+
Type varargsType;
2074+
unsigned callerDefaultArgIndex = 0;
2075+
for (unsigned i = 0, e = E->getElementMapping().size(); i != e; ++i) {
2076+
int subElem = E->getElementMapping()[i];
2077+
if (subElem == ArgumentShuffleExpr::DefaultInitialize)
2078+
continue;
2079+
if (subElem == ArgumentShuffleExpr::Variadic) {
2080+
varargsType = (E->getType()->castTo<TupleType>()
2081+
->getElement(i).getVarargBaseTy());
2082+
break;
2083+
}
2084+
if (subElem == ArgumentShuffleExpr::CallerDefaultInitialize) {
2085+
auto init = E->getCallerDefaultArgs()[callerDefaultArgIndex++];
2086+
if (!getOuterElementType(i)->isEqual(init->getType())) {
2087+
Out << "Type mismatch in ArgumentShuffleExpr\n";
2088+
abort();
2089+
}
2090+
continue;
2091+
}
2092+
if (!getOuterElementType(i)->isEqual(getSubElementType(subElem))) {
2093+
Out << "Type mismatch in ArgumentShuffleExpr\n";
2094+
abort();
2095+
}
2096+
}
2097+
if (varargsType) {
2098+
for (auto sourceIdx : E->getVariadicArgs()) {
2099+
if (!getSubElementType(sourceIdx)->isEqual(varargsType)) {
2100+
Out << "Vararg type mismatch in ArgumentShuffleExpr\n";
2101+
abort();
2102+
}
2103+
}
2104+
}
2105+
2106+
verifyCheckedBase(E);
2107+
}
2108+
20502109
void verifyChecked(DynamicTypeExpr *E) {
20512110
PrettyStackTraceExpr debugStack(Ctx, "verifying DynamicTypeExpr", E);
20522111

lib/AST/ASTWalker.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,23 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
656656
return E;
657657
}
658658

659+
Expr *visitArgumentShuffleExpr(ArgumentShuffleExpr *E) {
660+
if (Expr *E2 = doIt(E->getSubExpr())) {
661+
E->setSubExpr(E2);
662+
} else {
663+
return nullptr;
664+
}
665+
666+
for (auto &defaultArg : E->getCallerDefaultArgs()) {
667+
if (Expr *newDefaultArg = doIt(defaultArg))
668+
defaultArg = newDefaultArg;
669+
else
670+
return nullptr;
671+
}
672+
673+
return E;
674+
}
675+
659676
Expr *visitTryExpr(TryExpr *E) {
660677
if (Expr *E2 = doIt(E->getSubExpr())) {
661678
E->setSubExpr(E2);

lib/AST/Expr.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ ConcreteDeclRef Expr::getReferencedDecl() const {
323323
PASS_THROUGH_REFERENCE(ConstructorRefCall, getFn);
324324
PASS_THROUGH_REFERENCE(Load, getSubExpr);
325325
NO_REFERENCE(TupleShuffle);
326+
NO_REFERENCE(ArgumentShuffle);
326327
NO_REFERENCE(UnresolvedTypeConversion);
327328
PASS_THROUGH_REFERENCE(FunctionConversion, getSubExpr);
328329
PASS_THROUGH_REFERENCE(CovariantFunctionConversion, getSubExpr);
@@ -637,6 +638,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
637638

638639
case ExprKind::Load:
639640
case ExprKind::TupleShuffle:
641+
case ExprKind::ArgumentShuffle:
640642
case ExprKind::UnresolvedTypeConversion:
641643
case ExprKind::FunctionConversion:
642644
case ExprKind::CovariantFunctionConversion:
@@ -1349,6 +1351,24 @@ TupleShuffleExpr *TupleShuffleExpr::create(ASTContext &ctx,
13491351
VarargsArrayTy, CallerDefaultArgs, ty);
13501352
}
13511353

1354+
ArgumentShuffleExpr *ArgumentShuffleExpr::create(ASTContext &ctx,
1355+
Expr *subExpr,
1356+
ArrayRef<int> elementMapping,
1357+
TypeImpact typeImpact,
1358+
ConcreteDeclRef defaultArgsOwner,
1359+
ArrayRef<unsigned> VariadicArgs,
1360+
Type VarargsArrayTy,
1361+
ArrayRef<Expr *> CallerDefaultArgs,
1362+
Type ty) {
1363+
auto size = totalSizeToAlloc<Expr*, int, unsigned>(CallerDefaultArgs.size(),
1364+
elementMapping.size(),
1365+
VariadicArgs.size());
1366+
auto mem = ctx.Allocate(size, alignof(ArgumentShuffleExpr));
1367+
return ::new(mem) ArgumentShuffleExpr(subExpr, elementMapping, typeImpact,
1368+
defaultArgsOwner, VariadicArgs,
1369+
VarargsArrayTy, CallerDefaultArgs, ty);
1370+
}
1371+
13521372
SourceRange TupleExpr::getSourceRange() const {
13531373
SourceLoc start = SourceLoc();
13541374
SourceLoc end = SourceLoc();

0 commit comments

Comments
 (0)