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

Kill ArgumentShuffleExpr #23672

Merged
merged 3 commits into from
Mar 31, 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
249 changes: 80 additions & 169 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,19 +295,6 @@ class alignas(8) Expr {
NumElements : 16
);

SWIFT_INLINE_BITFIELD_FULL(ArgumentShuffleExpr, ImplicitConversionExpr, 2+16+16+16,
TypeImpact : 2,
: NumPadBits,
NumCallerDefaultArgs : 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
);

SWIFT_INLINE_BITFIELD(ForceValueExpr, Expr, 1,
ForcedIUO : 1
);
Expand Down Expand Up @@ -3020,157 +3007,6 @@ class DestructureTupleExpr final : public ImplicitConversionExpr,
}
};

/// 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 ArgumentShuffleExpr final : public ImplicitConversionExpr,
private llvm::TrailingObjects<ArgumentShuffleExpr, Expr *, int, unsigned> {
friend TrailingObjects;

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

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 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

// (ArgumentShuffleExpr 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;

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.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(),
getTrailingObjects<int>());
std::uninitialized_copy(VariadicArgs.begin(), VariadicArgs.end(),
getTrailingObjects<unsigned>());
}

public:
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.ArgumentShuffleExpr.NumElementMappings)};
}

/// What is the type impact of this shuffle?
TypeImpact getTypeImpact() const {
return TypeImpact(Bits.ArgumentShuffleExpr.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 {
return {getTrailingObjects<unsigned>(),
static_cast<size_t>(Bits.ArgumentShuffleExpr.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.ArgumentShuffleExpr.NumCallerDefaultArgs)};
}

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

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

/// LoadExpr - Turn an l-value into an r-value by performing a "load"
/// operation. This operation may actually be a logical operation,
/// i.e. one implemented using a call to a potentially user-defined
Expand Down Expand Up @@ -4021,7 +3857,7 @@ class DynamicTypeExpr : public Expr {
/// Opaque value expressions occur when a particular value within the AST
/// needs to be re-used without being re-evaluated or for a value that is
/// a placeholder. OpaqueValueExpr nodes are introduced by some other AST
/// node (say, a \c DynamicMemberRefExpr) and can only be used within the
/// node (say, an \c OpenExistentialExpr) and can only be used within the
/// subexpressions of that AST node.
class OpaqueValueExpr : public Expr {
SourceLoc Loc;
Expand All @@ -4037,6 +3873,82 @@ class OpaqueValueExpr : public Expr {
}
};

/// An expression referring to a default argument left unspecified at the
/// call site.
///
/// A DefaultArgumentExpr must only appear as a direct child of a
/// ParenExpr or a TupleExpr that is itself a call argument.
class DefaultArgumentExpr final : public Expr {
/// The owning declaration.
ConcreteDeclRef DefaultArgsOwner;

/// The caller parameter index.
unsigned ParamIndex;

/// The source location of the argument list.
SourceLoc Loc;

public:
explicit DefaultArgumentExpr(ConcreteDeclRef defaultArgsOwner, unsigned paramIndex,
SourceLoc loc, Type Ty)
: Expr(ExprKind::DefaultArgument, /*Implicit=*/true, Ty),
DefaultArgsOwner(defaultArgsOwner), ParamIndex(paramIndex), Loc(loc) { }

SourceRange getSourceRange() const {
return Loc;
}

ConcreteDeclRef getDefaultArgsOwner() const {
return DefaultArgsOwner;
}

unsigned getParamIndex() const {
return ParamIndex;
}

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

/// An expression referring to a caller-side default argument left unspecified
/// at the call site.
///
/// A CallerDefaultArgumentExpr must only appear as a direct child of a
/// ParenExpr or a TupleExpr that is itself a call argument.
///
/// FIXME: This only exists to distinguish caller default arguments from arguments
/// that were specified at the call site. Once we remove SanitizeExpr, we can remove
/// this hack too.
class CallerDefaultArgumentExpr final : public Expr {
/// The expression that is evaluated to produce the default argument value.
Expr *SubExpr;

/// The source location of the argument list.
SourceLoc Loc;

public:
explicit CallerDefaultArgumentExpr(Expr *subExpr, SourceLoc loc, Type Ty)
: Expr(ExprKind::CallerDefaultArgument, /*Implicit=*/true, Ty),
SubExpr(subExpr), Loc(loc) { }

SourceRange getSourceRange() const {
return Loc;
}

Expr *getSubExpr() const {
return SubExpr;
}

void setSubExpr(Expr *subExpr) {
SubExpr = subExpr;
}

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

/// ApplyExpr - Superclass of various function calls, which apply an argument to
/// a function to get a result.
class ApplyExpr : public Expr {
Expand All @@ -4047,8 +3959,7 @@ class ApplyExpr : public Expr {
llvm::PointerIntPair<Expr *, 1, bool> ArgAndIsSuper;

/// 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 ArgumentShuffleExpr.
/// subclasses, this means it is a \c ParenExpr or \c TupleExpr.
bool validateArg(Expr *e) const;

protected:
Expand Down Expand Up @@ -4112,7 +4023,7 @@ class ApplyExpr : public Expr {
E->getKind() <= ExprKind::Last_ApplyExpr;
}
};

/// CallExpr - Application of an argument to a function, which occurs
/// syntactically through juxtaposition with a TupleExpr whose
/// leading '(' is unspaced.
Expand Down Expand Up @@ -5428,7 +5339,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<ArgumentShuffleExpr>(e);
return isa<ParenExpr>(e) || isa<TupleExpr>(e);
Copy link
Contributor

Choose a reason for hiding this comment

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

I've been waiting for this day since I first added ApplyExpr::validateArg(). 🎉

}

inline Expr *const *CollectionExpr::getTrailingObjectsPointer() const {
Expand Down
3 changes: 2 additions & 1 deletion include/swift/AST/ExprNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ EXPR(VarargExpansion, Expr)
EXPR(DynamicType, Expr)
EXPR(RebindSelfInConstructor, Expr)
EXPR(OpaqueValue, Expr)
EXPR(DefaultArgument, Expr)
EXPR(CallerDefaultArgument, Expr)
EXPR(BindOptional, Expr)
EXPR(OptionalEvaluation, Expr)
EXPR(ForceValue, Expr)
Expand All @@ -144,7 +146,6 @@ ABSTRACT_EXPR(Apply, Expr)
ABSTRACT_EXPR(ImplicitConversion, Expr)
EXPR(Load, ImplicitConversionExpr)
EXPR(DestructureTuple, ImplicitConversionExpr)
EXPR(ArgumentShuffle, ImplicitConversionExpr)
EXPR(UnresolvedTypeConversion, ImplicitConversionExpr)
EXPR(FunctionConversion, ImplicitConversionExpr)
EXPR(CovariantFunctionConversion, ImplicitConversionExpr)
Expand Down
19 changes: 19 additions & 0 deletions include/swift/Sema/IDETypeChecking.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,25 @@ namespace swift {
/// the decl context.
bool resolveProtocolNames(DeclContext *DC, ArrayRef<const char *> names,
llvm::MapVector<ProtocolDecl*, StringRef> &result);

/// FIXME: All of the below goes away once CallExpr directly stores its
/// arguments.

/// Return value for getOriginalArgumentList().
struct OriginalArgumentList {
SmallVector<Expr *, 4> args;
SmallVector<Identifier, 4> labels;
SmallVector<SourceLoc, 4> labelLocs;
SourceLoc lParenLoc;
SourceLoc rParenLoc;
bool hasTrailingClosure = false;
};

/// When applying a solution to a constraint system, the type checker rewrites
/// argument lists of calls to insert default arguments and collect varargs.
/// Sometimes for diagnostics we want to work on the original argument list as
/// written by the user; this performs the reverse transformation.
OriginalArgumentList getOriginalArgumentList(Expr *expr);
}

#endif
Loading