From 8e4bde8b97e49fbe1999a50c911abb731a7b71e8 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Fri, 14 Sep 2018 11:58:16 -0700 Subject: [PATCH 1/6] SILGen: Remove dead code from Swift 3 removal --- lib/SILGen/SILGenApply.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 851eebeaf29e4..a772f86bf3514 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -2526,24 +2526,6 @@ class ArgEmitter { emitExpanded(std::move(arg), origParamType); return; } - - // Otherwise, if the substituted type is a tuple, then we should - // emit the tuple in its most general form, because there's a - // substitution of an opaque archetype to a tuple or function - // type in play. The most general convention is generally to - // pass the entire tuple indirectly, but if it's not - // materializable, the convention is actually to break it up - // into materializable chunks. See the comment in SILType.cpp. - // - // FIXME: Once -swift-version 3 code generation goes away, we - // can simplify this. - if (auto substTupleType = dyn_cast(substArgType)) { - if (shouldExpandTupleType(substTupleType)) { - assert(origParamType.isTypeParameter()); - emitExpanded(std::move(arg), origParamType); - return; - } - } } // Okay, everything else will be passed as a single value, one From 1913b557323094d1c0eca55de0f3dbdb3b94b622 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Fri, 14 Sep 2018 11:56:40 -0700 Subject: [PATCH 2/6] SILGen: Rename ArgumentSource::requiresCalleeToEvaluate() to ArgumentSource::isShuffle() Also, move the check to make it explicit that only a TupleShuffleExpr at the top level goes through the argument emission code path; a TupleShuffleExpr appearing inside a ParenExpr or TupleExpr is a tuple conversion, which is totally unrelated and emitted as an RValue. This is unfortunate and we should split off ArgumentShuffleExpr from TupleShuffleExpr, and eventually, fold ArgumentShuffleExpr into ApplyExpr. --- lib/SILGen/ArgumentSource.cpp | 27 ++++----------------------- lib/SILGen/ArgumentSource.h | 4 ++-- lib/SILGen/SILGenApply.cpp | 23 ++++++++++++----------- 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/lib/SILGen/ArgumentSource.cpp b/lib/SILGen/ArgumentSource.cpp index 50f9e0fc608e6..7a577532943c7 100644 --- a/lib/SILGen/ArgumentSource.cpp +++ b/lib/SILGen/ArgumentSource.cpp @@ -64,12 +64,13 @@ void ArgumentSource::rewriteType(CanType newType) & { llvm_unreachable("bad kind"); } -bool ArgumentSource::requiresCalleeToEvaluate() const { +bool ArgumentSource::isShuffle() const { switch (StoredKind) { case Kind::Invalid: llvm_unreachable("argument source is invalid"); case Kind::RValue: case Kind::LValue: + case Kind::Tuple: return false; case Kind::Expr: // FIXME: TupleShuffleExprs come in two flavors: @@ -85,28 +86,8 @@ bool ArgumentSource::requiresCalleeToEvaluate() const { // // It would be good to split up TupleShuffleExpr into these two // cases, and simplify ArgEmitter since it no longer has to deal - // with re-ordering. However for now, SubscriptExpr emits the - // index argument via the RValueEmitter, so the RValueEmitter has - // to know about varargs, duplicating some of the logic in - // ArgEmitter. - // - // Once this is fixed, we can also consider allowing subscripts - // to have default arguments. - if (auto *shuffleExpr = dyn_cast(asKnownExpr())) { - for (auto index : shuffleExpr->getElementMapping()) { - if (index == TupleShuffleExpr::DefaultInitialize || - index == TupleShuffleExpr::CallerDefaultInitialize || - index == TupleShuffleExpr::Variadic) - return true; - } - } - return false; - case Kind::Tuple: - for (auto &source : Storage.get(StoredKind).Elements) { - if (source.requiresCalleeToEvaluate()) - return true; - } - return false; + // with re-ordering. + return isa(asKnownExpr()); } llvm_unreachable("bad kind"); } diff --git a/lib/SILGen/ArgumentSource.h b/lib/SILGen/ArgumentSource.h index 6cf46fec22565..afe441acf3b24 100644 --- a/lib/SILGen/ArgumentSource.h +++ b/lib/SILGen/ArgumentSource.h @@ -292,8 +292,8 @@ class ArgumentSource { // This is a hack and should be avoided. void rewriteType(CanType newType) &; - /// Whether this argument source requires the callee to evaluate. - bool requiresCalleeToEvaluate() const; + /// Whether this argument source is a TupleShuffleExpr. + bool isShuffle() const; bool isObviouslyEqual(const ArgumentSource &other) const; diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index a772f86bf3514..ae600ec4ce781 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -2494,6 +2494,13 @@ class ArgEmitter { } void emitTopLevel(ArgumentSource &&arg, AbstractionPattern origParamType) { + if (arg.isShuffle()) { + auto *shuffle = cast(std::move(arg).asKnownExpr()); + emitShuffle(shuffle, origParamType); + maybeEmitForeignErrorArgument(); + return; + } + emit(std::move(arg), origParamType); maybeEmitForeignErrorArgument(); } @@ -2507,8 +2514,8 @@ class ArgEmitter { emitTopLevel(std::move(argSources[0]), origParamType); } else { for (auto i : indices(argSources)) { - emitTopLevel(std::move(argSources[i]), - origParamType.getTupleElementType(i)); + emit(std::move(argSources[i]), + origParamType.getTupleElementType(i)); } maybeEmitForeignErrorArgument(); } @@ -2519,10 +2526,9 @@ class ArgEmitter { auto substArgType = arg.getSubstRValueType(); if (!arg.hasLValueType()) { - // If it was a tuple in the original type, or the argument - // requires the callee to evaluate, the parameters will have - // been exploded. - if (origParamType.isTuple() || arg.requiresCalleeToEvaluate()) { + // If the unsubstituted function type has a parameter of tuple type, + // explode the tuple value. + if (origParamType.isTuple()) { emitExpanded(std::move(arg), origParamType); return; } @@ -2668,11 +2674,6 @@ class ArgEmitter { return; } - if (auto shuffle = dyn_cast(e)) { - emitShuffle(shuffle, origParamType); - return; - } - // Fall back to the r-value case. emitExpanded({ e, SGF.emitRValue(e) }, origParamType); } From 82ecbde678b28fd9d38241468a8eb23f0d46a239 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 15 Sep 2018 18:39:29 -0700 Subject: [PATCH 3/6] SILGen: Remove ArgumentSource::Kind::Tuple --- lib/SILGen/ArgumentSource.cpp | 87 ----------------------------------- lib/SILGen/ArgumentSource.h | 55 +--------------------- lib/SILGen/SILGenApply.cpp | 13 ------ 3 files changed, 1 insertion(+), 154 deletions(-) diff --git a/lib/SILGen/ArgumentSource.cpp b/lib/SILGen/ArgumentSource.cpp index 7a577532943c7..1172a8d7b5778 100644 --- a/lib/SILGen/ArgumentSource.cpp +++ b/lib/SILGen/ArgumentSource.cpp @@ -33,8 +33,6 @@ void ArgumentSource::rewriteType(CanType newType) & { llvm_unreachable("argument source is invalid"); case Kind::LValue: llvm_unreachable("cannot rewrite type of l-value"); - case Kind::Tuple: - llvm_unreachable("cannot rewrite type of tuple"); case Kind::RValue: Storage.get(StoredKind).Value.rewriteType(newType); return; @@ -70,7 +68,6 @@ bool ArgumentSource::isShuffle() const { llvm_unreachable("argument source is invalid"); case Kind::RValue: case Kind::LValue: - case Kind::Tuple: return false; case Kind::Expr: // FIXME: TupleShuffleExprs come in two flavors: @@ -102,46 +99,10 @@ RValue ArgumentSource::getAsRValue(SILGenFunction &SGF, SGFContext C) && { return std::move(*this).asKnownRValue(SGF); case Kind::Expr: return SGF.emitRValue(std::move(*this).asKnownExpr(), C); - case Kind::Tuple: - return std::move(*this).getKnownTupleAsRValue(SGF, C); } llvm_unreachable("bad kind"); } -RValue -ArgumentSource::getKnownTupleAsRValue(SILGenFunction &SGF, SGFContext C) && { - - return std::move(*this).withKnownTupleElementSources( - [&](SILLocation loc, CanTupleType type, - MutableArrayRef elements) { - // If there's a target initialization, and we can split it, do so. - if (auto init = C.getEmitInto()) { - if (init->canSplitIntoTupleElements()) { - // Split the tuple. - SmallVector scratch; - auto eltInits = init->splitIntoTupleElements(SGF, loc, type, scratch); - - // Emit each element into the corresponding element initialization. - for (auto i : indices(eltInits)) { - std::move(elements[i]).forwardInto(SGF, eltInits[i].get()); - } - - // Finish initialization. - init->finishInitialization(SGF); - - return RValue::forInContext(); - } - } - - // Otherwise, emit all of the elements into a single big r-value. - RValue result(type); - for (auto &element : elements) { - result.addElement(std::move(element).getAsRValue(SGF)); - } - return result; - }); -} - ManagedValue ArgumentSource::getAsSingleValue(SILGenFunction &SGF, SGFContext C) && { switch (StoredKind) { @@ -172,13 +133,6 @@ ManagedValue ArgumentSource::getAsSingleValue(SILGenFunction &SGF, return SGF.emitRValueAsSingleValue(e, C); } } - case Kind::Tuple: { - auto loc = getKnownTupleLocation(); - auto rvalue = std::move(*this).getKnownTupleAsRValue(SGF, C); - if (rvalue.isInContext()) - return ManagedValue::forInContext(); - return std::move(rvalue).getAsSingleValue(SGF, loc); - } } llvm_unreachable("bad kind"); } @@ -202,7 +156,6 @@ ManagedValue ArgumentSource::getConverted(SILGenFunction &SGF, llvm_unreachable("cannot get converted l-value"); case Kind::RValue: case Kind::Expr: - case Kind::Tuple: return SGF.emitConvertedRValue(getLocation(), conversion, C, [&](SILGenFunction &SGF, SILLocation loc, SGFContext C) { return std::move(*this).getAsSingleValue(SGF, C); @@ -227,13 +180,6 @@ void ArgumentSource::forwardInto(SILGenFunction &SGF, Initialization *dest) && { SGF.emitExprInto(e, dest); return; } - case Kind::Tuple: { - auto loc = getKnownTupleLocation(); - auto rvalue = std::move(*this).getKnownTupleAsRValue(SGF, SGFContext(dest)); - if (!rvalue.isInContext()) - std::move(rvalue).ensurePlusOne(SGF, loc).forwardInto(SGF, loc, dest); - return; - } } llvm_unreachable("bad kind"); } @@ -257,10 +203,6 @@ ArgumentSource ArgumentSource::borrow(SILGenFunction &SGF) const & { case Kind::Expr: { llvm_unreachable("cannot borrow an expression"); } - case Kind::Tuple: { - // FIXME: We can if we check the sub argument sources. - llvm_unreachable("cannot borrow a tuple"); - } } llvm_unreachable("bad kind"); } @@ -355,16 +297,6 @@ void ArgumentSource::dump(raw_ostream &out, unsigned indent) const { out << "LValue\n"; Storage.get(StoredKind).Value.dump(out, indent + 2); return; - case Kind::Tuple: { - out << "Tuple\n"; - auto &storage = Storage.get(StoredKind); - storage.SubstType.dump(out, indent + 2); - for (auto &elt : storage.Elements) { - elt.dump(out, indent + 2); - out << '\n'; - } - return; - } case Kind::RValue: out << "RValue\n"; Storage.get(StoredKind).Value.dump(out, indent + 2); @@ -426,17 +358,6 @@ bool ArgumentSource::isObviouslyEqual(const ArgumentSource &other) const { return false; // TODO? case Kind::Expr: return false; // TODO? - case Kind::Tuple: { - auto &selfTuple = Storage.get(StoredKind); - auto &otherTuple = other.Storage.get(other.StoredKind); - if (selfTuple.Elements.size() != otherTuple.Elements.size()) - return false; - for (auto i : indices(selfTuple.Elements)) { - if (!selfTuple.Elements[i].isObviouslyEqual(otherTuple.Elements[i])) - return false; - } - return true; - } } llvm_unreachable("bad kind"); } @@ -464,14 +385,6 @@ ArgumentSource ArgumentSource::copyForDiagnostics() const { return {getKnownRValueLocation(), asKnownRValue().copyForDiagnostics()}; case Kind::Expr: return asKnownExpr(); - case Kind::Tuple: { - auto &tuple = Storage.get(StoredKind); - SmallVector copiedElements; - for (auto &elt : tuple.Elements) { - copiedElements.push_back(elt.copyForDiagnostics()); - } - return {tuple.Loc, tuple.SubstType, copiedElements}; - } } llvm_unreachable("bad kind"); } diff --git a/lib/SILGen/ArgumentSource.h b/lib/SILGen/ArgumentSource.h index afe441acf3b24..2fba7c680b6b1 100644 --- a/lib/SILGen/ArgumentSource.h +++ b/lib/SILGen/ArgumentSource.h @@ -54,7 +54,6 @@ class ArgumentSource { RValue, LValue, Expr, - Tuple, }; struct RValueStorage { @@ -65,25 +64,9 @@ class ArgumentSource { LValue Value; SILLocation Loc; }; - struct TupleStorage { - CanTupleType SubstType; - SILLocation Loc; - std::vector Elements; - - TupleStorage(CanTupleType type, SILLocation loc, - MutableArrayRef elements) - : SubstType(type), Loc(loc) { - assert(type->getNumElements() == elements.size()); - Elements.reserve(elements.size()); - for (auto i : indices(elements)) { - Elements.push_back(std::move(elements[i])); - } - } - }; using StorageMembers = - ExternalUnionMembers; + ExternalUnionMembers; static StorageMembers::Index getStorageIndexForKind(Kind kind) { switch (kind) { @@ -92,7 +75,6 @@ class ArgumentSource { return StorageMembers::indexOf(); case Kind::LValue: return StorageMembers::indexOf(); case Kind::Expr: return StorageMembers::indexOf(); - case Kind::Tuple: return StorageMembers::indexOf(); } llvm_unreachable("bad kind"); } @@ -112,12 +94,6 @@ class ArgumentSource { assert(e && "initializing ArgumentSource with null expression"); Storage.emplace(StoredKind, e); } - ArgumentSource(SILLocation loc, CanTupleType type, - MutableArrayRef elements) - : StoredKind(Kind::Tuple) { - Storage.emplace(StoredKind, type, loc, elements); - } - // Cannot be copied. ArgumentSource(const ArgumentSource &other) = delete; ArgumentSource &operator=(const ArgumentSource &other) = delete; @@ -149,8 +125,6 @@ class ArgumentSource { return asKnownLValue().isValid(); case Kind::Expr: return asKnownExpr() != nullptr; - case Kind::Tuple: - return true; } llvm_unreachable("bad kind"); } @@ -165,8 +139,6 @@ class ArgumentSource { return asKnownLValue().getSubstFormalType(); case Kind::Expr: return asKnownExpr()->getType()->getInOutObjectType()->getCanonicalType(); - case Kind::Tuple: - return Storage.get(StoredKind).SubstType; } llvm_unreachable("bad kind"); } @@ -178,7 +150,6 @@ class ArgumentSource { return false; case Kind::LValue: return true; case Kind::Expr: return asKnownExpr()->isSemanticallyInOutExpr(); - case Kind::Tuple: return false; } llvm_unreachable("bad kind"); } @@ -193,8 +164,6 @@ class ArgumentSource { return getKnownLValueLocation(); case Kind::Expr: return asKnownExpr(); - case Kind::Tuple: - return getKnownTupleLocation(); } llvm_unreachable("bad kind"); } @@ -202,7 +171,6 @@ class ArgumentSource { bool isExpr() const & { return StoredKind == Kind::Expr; } bool isRValue() const & { return StoredKind == Kind::RValue; } bool isLValue() const & { return StoredKind == Kind::LValue; } - bool isTuple() const & { return StoredKind == Kind::Tuple; } /// Given that this source is storing an RValue, extract and clear /// that value. @@ -237,25 +205,6 @@ class ArgumentSource { return result; } - SILLocation getKnownTupleLocation() const & { - return Storage.get(StoredKind).Loc; - } - - template - ResultType withKnownTupleElementSources( - llvm::function_ref elts)> callback) && { - auto &tuple = Storage.get(StoredKind); - - auto result = callback(tuple.Loc, tuple.SubstType, tuple.Elements); - - // We've consumed the tuple. - Storage.resetToEmpty(StoredKind, Kind::Invalid); - StoredKind = Kind::Invalid; - - return result; - } - /// Return an unowned handle to the r-value stored in this source. Undefined /// if this ArgumentSource is not an rvalue. RValue &peekRValue() &; @@ -311,8 +260,6 @@ class ArgumentSource { Expr *asKnownExpr() const & { return Storage.get(StoredKind); } - - RValue getKnownTupleAsRValue(SILGenFunction &SGF, SGFContext C) &&; }; class PreparedArguments { diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index ae600ec4ce781..a34d26af2d272 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -2647,19 +2647,6 @@ class ArgEmitter { return; } - // If we're working with a tuple source, expand it. - if (arg.isTuple()) { - (void) std::move(arg).withKnownTupleElementSources( - [&](SILLocation loc, CanTupleType type, - MutableArrayRef elts) { - for (auto i : indices(elts)) { - emit(std::move(elts[i]), origParamType.getTupleElementType(i)); - } - return 0; // We need a fake return value because won't compile. - }); - return; - } - // Otherwise, we're working with an expression. Expr *e = std::move(arg).asKnownExpr(); e = e->getSemanticsProvidingExpr(); From 17cdc663a38c18ece34f52e73529ecb65908de8e Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 15 Sep 2018 21:19:31 -0700 Subject: [PATCH 4/6] SILGen: Remove ArgumentSource::rewriteType() --- lib/SILGen/ArgumentSource.cpp | 35 ----------------------------------- lib/SILGen/ArgumentSource.h | 3 --- 2 files changed, 38 deletions(-) diff --git a/lib/SILGen/ArgumentSource.cpp b/lib/SILGen/ArgumentSource.cpp index 1172a8d7b5778..de97a4371073a 100644 --- a/lib/SILGen/ArgumentSource.cpp +++ b/lib/SILGen/ArgumentSource.cpp @@ -27,41 +27,6 @@ RValue &ArgumentSource::peekRValue() & { return Storage.get(StoredKind).Value; } -void ArgumentSource::rewriteType(CanType newType) & { - switch (StoredKind) { - case Kind::Invalid: - llvm_unreachable("argument source is invalid"); - case Kind::LValue: - llvm_unreachable("cannot rewrite type of l-value"); - case Kind::RValue: - Storage.get(StoredKind).Value.rewriteType(newType); - return; - case Kind::Expr: - Expr *&expr = Storage.get(StoredKind); - CanType oldType = expr->getType()->getCanonicalType(); - - // Usually nothing is required. - if (oldType == newType) return; - - // Sometimes we need to wrap the expression in a single-element tuple. - // This is only necessary because we don't break down the argument list - // when dealing with SILGenApply. - if (auto newTuple = dyn_cast(newType)) { - if (newTuple->getNumElements() == 1 && - newTuple.getElementType(0) == oldType) { - expr = TupleExpr::create(newType->getASTContext(), - SourceLoc(), expr, {}, {}, SourceLoc(), - /*trailing closure*/ false, - /*implicit*/ true, newType); - return; - } - } - - llvm_unreachable("unimplemented! hope it doesn't happen"); - } - llvm_unreachable("bad kind"); -} - bool ArgumentSource::isShuffle() const { switch (StoredKind) { case Kind::Invalid: diff --git a/lib/SILGen/ArgumentSource.h b/lib/SILGen/ArgumentSource.h index 2fba7c680b6b1..8a081c2c03a43 100644 --- a/lib/SILGen/ArgumentSource.h +++ b/lib/SILGen/ArgumentSource.h @@ -238,9 +238,6 @@ class ArgumentSource { AbstractionPattern origFormalType, SILType expectedType = SILType()) &&; - // This is a hack and should be avoided. - void rewriteType(CanType newType) &; - /// Whether this argument source is a TupleShuffleExpr. bool isShuffle() const; From 3527e54bbdcd5d59bc0c596461fe0fb9d871b9b8 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 15 Sep 2018 21:19:56 -0700 Subject: [PATCH 5/6] SILGen: Move usages of AbstractionPattern::getFunctionInputType() closer to their uses --- lib/SILGen/SILGenApply.cpp | 59 ++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index a34d26af2d272..231f1eee76a7d 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -1729,16 +1729,8 @@ static unsigned getFlattenedValueCount(AbstractionPattern origType, return count; } -static AbstractionPattern claimNextParamClause(AbstractionPattern &type) { - auto result = type.getFunctionInputType(); - type = type.getFunctionResultType(); - return result; -} - -static CanType claimNextParamClause(CanAnyFunctionType &type) { - auto result = type.getInput(); +static void claimNextParamClause(CanAnyFunctionType &type) { type = dyn_cast(type.getResult()); - return result; } namespace { @@ -2505,26 +2497,26 @@ class ArgEmitter { maybeEmitForeignErrorArgument(); } - void emitTopLevel(PreparedArguments &&args, - AbstractionPattern origParamType) { + void emitPreparedArgs(PreparedArguments &&args, + AbstractionPattern origFormalType) { assert(args.isValid()); auto argSources = std::move(args).getSources(); + if (args.isScalar()) { assert(argSources.size() == 1); - emitTopLevel(std::move(argSources[0]), origParamType); + emitTopLevel(std::move(argSources[0]), + origFormalType.getFunctionInputType()); } else { for (auto i : indices(argSources)) { emit(std::move(argSources[i]), - origParamType.getTupleElementType(i)); + origFormalType.getFunctionParamType(i)); + maybeEmitForeignErrorArgument(); } - maybeEmitForeignErrorArgument(); } } private: void emit(ArgumentSource &&arg, AbstractionPattern origParamType) { - auto substArgType = arg.getSubstRValueType(); - if (!arg.hasLValueType()) { // If the unsubstituted function type has a parameter of tuple type, // explode the tuple value. @@ -2557,6 +2549,7 @@ class ArgEmitter { // Make sure we use the same value category for these so that we // can hereafter just use simple equality checks to test for // abstraction. + auto substArgType = arg.getSubstRValueType(); SILType loweredSubstArgType = SGF.getLoweredType(substArgType); if (param.isIndirectInOut()) { loweredSubstArgType = @@ -2649,7 +2642,6 @@ class ArgEmitter { // Otherwise, we're working with an expression. Expr *e = std::move(arg).asKnownExpr(); - e = e->getSemanticsProvidingExpr(); // If the source expression is a tuple literal, we can break it // up directly. @@ -3662,17 +3654,19 @@ class CallSite { bool throws() const { return Throws; } /// Evaluate arguments and begin any inout formal accesses. - void emit(SILGenFunction &SGF, AbstractionPattern origParamType, + void emit(SILGenFunction &SGF, AbstractionPattern origFormalType, ParamLowering &lowering, SmallVectorImpl &args, SmallVectorImpl &delayedArgs, const Optional &foreignError, ImportAsMemberStatus foreignSelf) && { + auto origParamType = origFormalType.getFunctionInputType(); + auto params = lowering.claimParams(origParamType, getSubstArgType(), foreignError, foreignSelf); ArgEmitter emitter(SGF, lowering.Rep, params, args, delayedArgs, foreignError, foreignSelf); - emitter.emitTopLevel(std::move(Args), origParamType); + emitter.emitPreparedArgs(std::move(Args), origFormalType); } /// Take the arguments for special processing, in place of the above. @@ -3873,7 +3867,7 @@ static AbstractionPattern getUncurriedOrigFormalResultType(AbstractionPattern origFormalType, unsigned numUncurriedSites) { for (unsigned i = 0, e = numUncurriedSites; i < e; ++i) { - claimNextParamClause(origFormalType); + origFormalType = origFormalType.getFunctionResultType(); } return origFormalType; @@ -4079,7 +4073,7 @@ CallEmission::applyEnumElementConstructor(SGFContext C) { CanType formalResultType = firstLevelResult.formalType.getResult(); // Ignore metatype argument - claimNextParamClause(origFormalType); + origFormalType = origFormalType.getFunctionResultType(); claimNextParamClause(firstLevelResult.formalType); std::move(uncurriedSites[0]).forward().getAsSingleValue(SGF); @@ -4088,7 +4082,7 @@ CallEmission::applyEnumElementConstructor(SGFContext C) { if (element->hasAssociatedValues()) { assert(uncurriedSites.size() == 2); formalResultType = firstLevelResult.formalType.getResult(); - claimNextParamClause(origFormalType); + origFormalType = origFormalType.getFunctionResultType(); claimNextParamClause(firstLevelResult.formalType); payload = std::move(uncurriedSites[1]).forward(); } else { @@ -4203,7 +4197,7 @@ CallEmission::applySpecializedEmitter(SpecializedEmitter &specializedEmitter, assert(!formalApplyType->getExtInfo().throws()); CanType formalResultType = formalApplyType.getResult(); SILLocation uncurriedLoc = uncurriedSites[0].Loc; - claimNextParamClause(origFormalType); + origFormalType = origFormalType.getFunctionResultType(); claimNextParamClause(firstLevelResult.formalType); // We should be able to enforce that these arguments are @@ -4293,7 +4287,6 @@ ApplyOptions CallEmission::emitArgumentsForNormalApply( // Collect the arguments to the uncurried call. for (auto &site : uncurriedSites) { - AbstractionPattern origParamType = claimNextParamClause(origFormalType); formalApplyType = cast(formalType); claimNextParamClause(formalType); uncurriedLoc = site.Loc; @@ -4301,7 +4294,7 @@ ApplyOptions CallEmission::emitArgumentsForNormalApply( bool isParamSite = &site == &uncurriedSites.back(); - std::move(site).emit(SGF, origParamType, paramLowering, args.back(), + std::move(site).emit(SGF, origFormalType, paramLowering, args.back(), delayedArgs, // Claim the foreign error with the method // formal params. @@ -4309,6 +4302,8 @@ ApplyOptions CallEmission::emitArgumentsForNormalApply( // Claim the foreign "self" with the self // param. isParamSite ? ImportAsMemberStatus() : foreignSelf); + + origFormalType = origFormalType.getFunctionResultType(); } } assert(uncurriedLoc); @@ -4365,21 +4360,21 @@ RValue CallEmission::applyRemainingCallSites(RValue &&result, // TODO: foreign errors for block or function pointer values? assert(substFnType->hasErrorResult() || formalTypeThrows); - AbstractionPattern origParamType = claimNextParamClause(origFormalType); - AbstractionPattern origResultType = origFormalType; - SGFContext context = i == size - 1 ? C : SGFContext(); // Create the callee type info and initialize our indirect results. CalleeTypeInfo calleeTypeInfo( - substFnType, origResultType, extraSites[i].getSubstResultType(), - Optional(), foreignSelf); + substFnType, + origFormalType.getFunctionResultType(), + extraSites[i].getSubstResultType(), + Optional(), + foreignSelf); ResultPlanPtr resultPtr = ResultPlanBuilder::computeResultPlan(SGF, calleeTypeInfo, loc, context); ArgumentScope argScope(SGF, loc); std::move(extraSites[i]) - .emit(SGF, origParamType, paramLowering, siteArgs, delayedArgs, + .emit(SGF, origFormalType, paramLowering, siteArgs, delayedArgs, calleeTypeInfo.foreignError, calleeTypeInfo.foreignSelf); if (!delayedArgs.empty()) { emitDelayedArguments(SGF, delayedArgs, siteArgs); @@ -4388,6 +4383,8 @@ RValue CallEmission::applyRemainingCallSites(RValue &&result, result = SGF.emitApply(std::move(resultPtr), std::move(argScope), loc, functionMV, {}, siteArgs, calleeTypeInfo, ApplyOptions::None, context); + + origFormalType = origFormalType.getFunctionResultType(); } return std::move(result); From 817555254c3f84210ef195f55adb248e150f7ca9 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 15 Sep 2018 21:02:56 -0700 Subject: [PATCH 6/6] SILGen: Change PreparedArguments to use an array of AnyFunctionType::Param This solves a recently-added TODO, eliminating two usages of FunctionType::getInput() from SILGen. --- lib/SILGen/ArgumentSource.cpp | 6 +- lib/SILGen/ArgumentSource.h | 45 +++++++-------- lib/SILGen/SILGenApply.cpp | 101 +++++++++++++++++++++++----------- lib/SILGen/SILGenExpr.cpp | 15 +++-- 4 files changed, 101 insertions(+), 66 deletions(-) diff --git a/lib/SILGen/ArgumentSource.cpp b/lib/SILGen/ArgumentSource.cpp index de97a4371073a..049b04fc38470 100644 --- a/lib/SILGen/ArgumentSource.cpp +++ b/lib/SILGen/ArgumentSource.cpp @@ -275,7 +275,7 @@ void ArgumentSource::dump(raw_ostream &out, unsigned indent) const { } void PreparedArguments::emplaceEmptyArgumentList(SILGenFunction &SGF) { - emplace(CanType(TupleType::getEmpty(SGF.getASTContext())), /*scalar*/ false); + emplace({}, /*scalar*/ false); assert(isValid()); } @@ -284,7 +284,7 @@ PreparedArguments::copy(SILGenFunction &SGF, SILLocation loc) const { if (isNull()) return PreparedArguments(); assert(isValid()); - PreparedArguments result(getFormalType(), isScalar()); + PreparedArguments result(getParams(), isScalar()); for (auto &elt : Arguments) { assert(elt.isRValue()); result.add(elt.getKnownRValueLocation(), @@ -332,7 +332,7 @@ PreparedArguments PreparedArguments::copyForDiagnostics() const { return PreparedArguments(); assert(isValid()); - PreparedArguments result(getFormalType(), isScalar()); + PreparedArguments result(getParams(), isScalar()); for (auto &arg : Arguments) { result.Arguments.push_back(arg.copyForDiagnostics()); } diff --git a/lib/SILGen/ArgumentSource.h b/lib/SILGen/ArgumentSource.h index 8a081c2c03a43..7c5c9ca7b6a38 100644 --- a/lib/SILGen/ArgumentSource.h +++ b/lib/SILGen/ArgumentSource.h @@ -260,14 +260,15 @@ class ArgumentSource { }; class PreparedArguments { - // TODO: replace this formal type with an array of parameter types. - CanType FormalType; + SmallVector Params; std::vector Arguments; - bool IsScalar = false; + unsigned IsScalar : 1; + unsigned IsNull : 1; public: - PreparedArguments() {} - PreparedArguments(CanType formalType, bool isScalar) { - emplace(formalType, isScalar); + PreparedArguments() : IsScalar(false), IsNull(true) {} + PreparedArguments(ArrayRef params, bool isScalar) + : IsNull(true) { + emplace(params, isScalar); } // Move-only. @@ -275,39 +276,34 @@ class PreparedArguments { PreparedArguments &operator=(const PreparedArguments &) = delete; PreparedArguments(PreparedArguments &&other) - : FormalType(other.FormalType), Arguments(std::move(other.Arguments)), - IsScalar(other.IsScalar) { - other.FormalType = CanType(); - } + : Params(std::move(other.Params)), Arguments(std::move(other.Arguments)), + IsScalar(other.IsScalar), IsNull(other.IsNull) {} PreparedArguments &operator=(PreparedArguments &&other) { - FormalType = other.FormalType; + Params = std::move(other.Params); IsScalar = other.IsScalar; Arguments = std::move(other.Arguments); - other.FormalType = CanType(); + IsNull = other.IsNull; + other.IsNull = true; return *this; } /// Returns true if this is a null argument list. Note that this always /// indicates the total absence of an argument list rather than the /// possible presence of an empty argument list. - bool isNull() const { return !FormalType; } + bool isNull() const { return IsNull; } /// Returns true if this is a non-null and completed argument list. bool isValid() const { assert(!isNull()); - if (IsScalar) { - return Arguments.size() == 1; - } else if (auto tuple = dyn_cast(FormalType)) { - return Arguments.size() == tuple->getNumElements(); - } else { + if (IsScalar) return Arguments.size() == 1; - } + return Arguments.size() == Params.size(); } /// Return the formal type of this argument list. - CanType getFormalType() const { + ArrayRef getParams() const { assert(!isNull()); - return FormalType; + return Params; } /// Is this a single-argument list? Note that the argument might be a tuple. @@ -322,12 +318,11 @@ class PreparedArguments { } /// Emplace a (probably incomplete) argument list. - void emplace(CanType formalType, bool isScalar) { + void emplace(ArrayRef params, bool isScalar) { assert(isNull()); - assert(!formalType->hasTypeParameter() && "should be a contextual type!"); - assert(isScalar || isa(formalType)); - FormalType = formalType; + Params.append(params.begin(), params.end()); IsScalar = isScalar; + IsNull = false; } /// Emplace an empty argument list. diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 231f1eee76a7d..895cd4416a52c 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -1716,6 +1716,8 @@ static unsigned getFlattenedValueCount(AbstractionPattern origType, // If the original type is opaque and the substituted type is // materializable, the count is 1 anyway. + // + // FIXME: Should always be materializable here. if (origType.isTypeParameter() && substTuple->isMaterializable()) return 1; @@ -3536,11 +3538,25 @@ struct ParamLowering { fnConv(fnType, SGF.SGM.M) {} ClaimedParamsRef - claimParams(AbstractionPattern origParamType, CanType substParamType, + claimParams(AbstractionPattern origFormalType, + ArrayRef substParams, const Optional &foreignError, ImportAsMemberStatus foreignSelf) { - unsigned count = - getFlattenedValueCount(origParamType, substParamType, foreignSelf); + unsigned count = 0; + if (!foreignSelf.isStatic()) { + for (auto i : indices(substParams)) { + auto substParam = substParams[i]; + if (substParam.isInOut()) { + count += 1; + continue; + } + count += getFlattenedValueCount( + origFormalType.getFunctionParamType(i), + substParam.getParameterType()->getCanonicalType(), + ImportAsMemberStatus()); + } + } + if (foreignError) count++; @@ -3617,7 +3633,13 @@ class CallSite { : Loc(apply), SubstResultType(apply->getType()->getCanonicalType()), Throws(apply->throws()) { Expr *arg = apply->getArg(); - Args.emplace(arg->getType()->getCanonicalType(), /*scalar*/true); + + SmallVector params; + AnyFunctionType::decomposeInput(arg->getType(), params); + + // FIXME: Split up the argument expression here instead of passing + // scalar=true. + Args.emplace(params, /*scalar*/true); Args.addArbitrary(arg); } @@ -3628,14 +3650,19 @@ class CallSite { assert(Args.isValid()); } + // FIXME: Remove this entry point. CallSite(SILLocation loc, ArgumentSource &&value, CanType resultType, bool throws) - : Loc(loc), SubstResultType(resultType), - // FIXME: Refactor InOutType usage here - Args(value.hasLValueType() - ? CanInOutType::get(value.getSubstRValueType()) - : value.getSubstRValueType(), /*scalar*/ true), Throws(throws) { + : Loc(loc), SubstResultType(resultType), Throws(throws) { + + auto type = (value.hasLValueType() + ? CanInOutType::get(value.getSubstRValueType()) + : value.getSubstRValueType()); + SmallVector params; + AnyFunctionType::decomposeInput(type, params); + Args.emplace(params, /*scalar*/true); Args.addArbitrary(std::move(value)); + assert(Args.isValid()); } CallSite(SILLocation loc, ArgumentSource &&value, CanAnyFunctionType fnType) @@ -3644,8 +3671,8 @@ class CallSite { CallSite(SILLocation loc, PreparedArguments &&args, CanAnyFunctionType fnType) : CallSite(loc, std::move(args), fnType.getResult(), fnType->throws()) {} - /// Return the substituted, unlowered AST type of the argument. - CanType getSubstArgType() const { return Args.getFormalType(); } + /// Return the substituted, unlowered AST parameter types of the argument. + ArrayRef getParams() const { return Args.getParams(); } /// Return the substituted, unlowered AST type of the result of /// this application. @@ -3659,9 +3686,7 @@ class CallSite { SmallVectorImpl &delayedArgs, const Optional &foreignError, ImportAsMemberStatus foreignSelf) && { - auto origParamType = origFormalType.getFunctionInputType(); - - auto params = lowering.claimParams(origParamType, getSubstArgType(), + auto params = lowering.claimParams(origFormalType, getParams(), foreignError, foreignSelf); ArgEmitter emitter(SGF, lowering.Rep, params, args, delayedArgs, @@ -5498,10 +5523,25 @@ SILGenFunction::prepareSubscriptIndices(SubscriptDecl *subscript, // strategy. // Currently we use the substituted type so that we can reconstitute these // as RValues. + Type interfaceType = subscript->getInterfaceType(); + + CanFunctionType substFnType; + if (subs) + substFnType = cast(interfaceType + ->castTo() + ->substGenericArgs(subs) + ->getCanonicalType()); + else + substFnType = cast(interfaceType + ->getCanonicalType()); + + auto substParams = substFnType->getParams(); - auto substArgType = indexExpr->getType()->getCanonicalType(); SmallVector substParamTys; - collectFakeIndexParameters(SGM, substArgType, substParamTys); + for (auto substParam : substParams) { + auto substParamType = substParam.getParameterType()->getCanonicalType(); + collectFakeIndexParameters(SGM, substParamType, substParamTys); + } SmallVector argValues; SmallVector delayedArgs; @@ -5512,27 +5552,24 @@ SILGenFunction::prepareSubscriptIndices(SubscriptDecl *subscript, /*foreign error*/None, ImportAsMemberStatus()); - emitter.emitTopLevel(indexExpr, AbstractionPattern(substArgType)); + emitter.emitTopLevel(indexExpr, + AbstractionPattern(substFnType).getFunctionInputType()); // TODO: do something to preserve LValues in the delayed arguments? if (!delayedArgs.empty()) emitDelayedArguments(*this, delayedArgs, argValues); - bool isScalar = subscript->getIndices()->size() == 1; - PreparedArguments result(substArgType, isScalar); - if (isScalar) { - result.add(indexExpr, RValue(*this, argValues, substArgType)); - } else { - ArrayRef remainingArgs = argValues; - auto substArgTupleType = cast(substArgType); - for (auto substArgEltType : substArgTupleType.getElementTypes()) { - auto count = RValue::getRValueSize(substArgEltType); - RValue elt(*this, remainingArgs.slice(0, count), substArgEltType); - result.add(indexExpr, std::move(elt)); - remainingArgs = remainingArgs.slice(count); - } - assert(remainingArgs.empty()); + PreparedArguments result(substParams, /*isScalar=*/false); + + ArrayRef remainingArgs = argValues; + for (auto substParam : substParams) { + auto substParamType = substParam.getParameterType()->getCanonicalType(); + auto count = RValue::getRValueSize(substParamType); + RValue elt(*this, remainingArgs.slice(0, count), substParamType); + result.add(indexExpr, std::move(elt)); + remainingArgs = remainingArgs.slice(count); } + assert(remainingArgs.empty()); assert(result.isValid()); return result; @@ -5600,7 +5637,7 @@ void SILGenFunction::emitSetAccessor(SILLocation loc, SILDeclRef set, // (value) or (value, indices...) bool isScalar = subscriptIndices.isNull() || std::move(subscriptIndices).getSources().empty(); - PreparedArguments values(accessType.getInput(), isScalar); + PreparedArguments values(accessType->getParams(), isScalar); values.addArbitrary(std::move(setValue)); if (!isScalar) { unsigned paramIndex = 1; diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index b4506d17095c4..5ee1f150c8b3c 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -2808,20 +2808,23 @@ loadIndexValuesForKeyPathComponent(SILGenFunction &SGF, SILLocation loc, if (!isa(storage)) return PreparedArguments(); - SmallVector indexElts; + SmallVector indexParams; for (auto &elt : indexes) { - indexElts.push_back(SGF.F.mapTypeIntoContext(elt.first)); + // FIXME: Varargs? + indexParams.emplace_back(SGF.F.mapTypeIntoContext(elt.first)); } - auto indexTupleTy = TupleType::get(indexElts, SGF.getASTContext()) - ->getCanonicalType(); - PreparedArguments indexValues(indexTupleTy, /*scalar*/ indexes.size() == 1); + PreparedArguments indexValues(indexParams, /*scalar*/ indexes.size() == 1); if (indexes.empty()) { assert(indexValues.isValid()); return indexValues; } - auto indexLoweredTy = SGF.getLoweredType(indexTupleTy); + auto indexLoweredTy = + SGF.getLoweredType( + AnyFunctionType::composeInput(SGF.getASTContext(), indexParams, + /*canonicalVararg=*/false)); + auto addr = SGF.B.createPointerToAddress(loc, pointer, indexLoweredTy.getAddressType(), /*isStrict*/ false);