diff --git a/lib/SILGen/ASTVisitor.h b/lib/SILGen/ASTVisitor.h index 710f464808618..3f0429aa02dfd 100644 --- a/lib/SILGen/ASTVisitor.h +++ b/lib/SILGen/ASTVisitor.h @@ -57,7 +57,8 @@ class ASTVisitor : public swift::ASTVisitor(this)->visit(E->getSubExpr(), + std::forward(AA)...); } ExprRetTy visitIdentityExpr(IdentityExpr *E, Args...AA) { diff --git a/lib/SILGen/ArgumentSource.cpp b/lib/SILGen/ArgumentSource.cpp index e221bc52b8375..e3bbbf789ca65 100644 --- a/lib/SILGen/ArgumentSource.cpp +++ b/lib/SILGen/ArgumentSource.cpp @@ -27,19 +27,6 @@ RValue &ArgumentSource::peekRValue() & { return Storage.get(StoredKind).Value; } -bool ArgumentSource::isShuffle() const { - switch (StoredKind) { - case Kind::Invalid: - llvm_unreachable("argument source is invalid"); - case Kind::RValue: - case Kind::LValue: - return false; - case Kind::Expr: - return isa(asKnownExpr()); - } - llvm_unreachable("bad kind"); -} - RValue ArgumentSource::getAsRValue(SILGenFunction &SGF, SGFContext C) && { switch (StoredKind) { case Kind::Invalid: @@ -261,9 +248,21 @@ void ArgumentSource::dump(raw_ostream &out, unsigned indent) const { llvm_unreachable("bad kind"); } -void PreparedArguments::emplaceEmptyArgumentList(SILGenFunction &SGF) { - emplace({}, /*scalar*/ false); - assert(isValid()); +PreparedArguments::PreparedArguments( + ArrayRef params, + Expr *arg) : PreparedArguments(params) { + if (isa(arg)) { + IsScalar = true; + addArbitrary(arg); + } else if (auto *PE = dyn_cast(arg)) + addArbitrary(PE->getSubExpr()); + else if (auto *TE = dyn_cast(arg)) { + for (auto *elt : TE->getElements()) + addArbitrary(elt); + } else { + // FIXME: All ApplyExprs should have a ParenExpr or TupleExpr as their argument + addArbitrary(arg); + } } PreparedArguments @@ -271,7 +270,8 @@ PreparedArguments::copy(SILGenFunction &SGF, SILLocation loc) const { if (isNull()) return PreparedArguments(); assert(isValid()); - PreparedArguments result(getParams(), isScalar()); + PreparedArguments result(getParams()); + result.IsScalar = isScalar(); for (auto &elt : Arguments) { assert(elt.isRValue()); result.add(elt.getKnownRValueLocation(), @@ -319,7 +319,8 @@ PreparedArguments PreparedArguments::copyForDiagnostics() const { return PreparedArguments(); assert(isValid()); - PreparedArguments result(getParams(), isScalar()); + PreparedArguments result(getParams()); + result.IsScalar = isScalar(); for (auto &arg : Arguments) { result.Arguments.push_back(arg.copyForDiagnostics()); } diff --git a/lib/SILGen/ArgumentSource.h b/lib/SILGen/ArgumentSource.h index 4f49a4a56ed25..b856a15f15710 100644 --- a/lib/SILGen/ArgumentSource.h +++ b/lib/SILGen/ArgumentSource.h @@ -240,9 +240,6 @@ class ArgumentSource { AbstractionPattern origFormalType, SILType expectedType = SILType()) &&; - /// Whether this argument source is an ArgumentShuffleExpr. - bool isShuffle() const; - bool isObviouslyEqual(const ArgumentSource &other) const; ArgumentSource copyForDiagnostics() const; @@ -268,11 +265,14 @@ class PreparedArguments { unsigned IsNull : 1; public: PreparedArguments() : IsScalar(false), IsNull(true) {} - PreparedArguments(ArrayRef params, bool isScalar) - : IsNull(true) { - emplace(params, isScalar); + explicit PreparedArguments(ArrayRef params) + : IsScalar(false), IsNull(true) { + emplace(params); } + // Decompse an argument list expression. + PreparedArguments(ArrayRef params, Expr *arg); + // Move-only. PreparedArguments(const PreparedArguments &) = delete; PreparedArguments &operator=(const PreparedArguments &) = delete; @@ -320,16 +320,13 @@ class PreparedArguments { } /// Emplace a (probably incomplete) argument list. - void emplace(ArrayRef params, bool isScalar) { + void emplace(ArrayRef params) { assert(isNull()); Params.append(params.begin(), params.end()); - IsScalar = isScalar; + IsScalar = false; IsNull = false; } - /// Emplace an empty argument list. - void emplaceEmptyArgumentList(SILGenFunction &SGF); - /// Add an emitted r-value argument to this argument list. void add(SILLocation loc, RValue &&arg) { assert(!isNull()); diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index a868ce8a31b13..efd687c827698 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -826,7 +826,10 @@ class SILGenApply : public Lowering::ExprVisitor { /// The lvalue or rvalue representing the argument source of self. ArgumentSource selfParam; + + /// The method type with self stripped off (NOT the type of the self value). Type selfType; + std::vector callSites; Expr *sideEffect = nullptr; @@ -1635,9 +1638,9 @@ class SILGenApply : public Lowering::ExprVisitor { } // end anonymous namespace -static RValue emitStringLiteral(SILGenFunction &SGF, Expr *E, StringRef Str, - SGFContext C, - StringLiteralExpr::Encoding encoding) { +static PreparedArguments emitStringLiteral(SILGenFunction &SGF, Expr *E, + StringRef Str, SGFContext C, + StringLiteralExpr::Encoding encoding) { uint64_t Length; bool isASCII = true; for (unsigned char c : Str) { @@ -1663,8 +1666,12 @@ static RValue emitStringLiteral(SILGenFunction &SGF, Expr *E, StringRef Str, SILValue UnicodeScalarValue = SGF.B.createIntegerLiteral(E, Int32Ty, unicode::extractFirstUnicodeScalar(Str)); - return RValue(SGF, E, Int32Ty.getASTType(), - ManagedValue::forUnmanaged(UnicodeScalarValue)); + + AnyFunctionType::Param param(Int32Ty.getASTType()); + PreparedArguments args({param}); + args.add(E, RValue(SGF, E, Int32Ty.getASTType(), + ManagedValue::forUnmanaged(UnicodeScalarValue))); + return args; } } @@ -1679,20 +1686,21 @@ static RValue emitStringLiteral(SILGenFunction &SGF, Expr *E, StringRef Str, auto Int1Ty = SILType::getBuiltinIntegerType(1, SGF.getASTContext()); auto *isASCIIInst = SGF.B.createIntegerLiteral(E, Int1Ty, isASCII); + ManagedValue EltsArray[] = { ManagedValue::forUnmanaged(string), ManagedValue::forUnmanaged(lengthInst), ManagedValue::forUnmanaged(isASCIIInst) }; - TupleTypeElt TypeEltsArray[] = { - EltsArray[0].getType().getASTType(), - EltsArray[1].getType().getASTType(), - EltsArray[2].getType().getASTType() + AnyFunctionType::Param TypeEltsArray[] = { + AnyFunctionType::Param(EltsArray[0].getType().getASTType()), + AnyFunctionType::Param(EltsArray[1].getType().getASTType()), + AnyFunctionType::Param(EltsArray[2].getType().getASTType()) }; ArrayRef Elts; - ArrayRef TypeElts; + ArrayRef TypeElts; switch (instEncoding) { case StringLiteralInst::Encoding::UTF16: Elts = llvm::makeArrayRef(EltsArray).slice(0, 2); @@ -1709,9 +1717,11 @@ static RValue emitStringLiteral(SILGenFunction &SGF, Expr *E, StringRef Str, llvm_unreachable("these cannot be formed here"); } - CanType ty = - TupleType::get(TypeElts, SGF.getASTContext())->getCanonicalType(); - return RValue(SGF, Elts, ty); + PreparedArguments args(TypeElts); + for (unsigned i = 0, e = Elts.size(); i != e; ++i) { + args.add(E, RValue(SGF, Elts[i], CanType(TypeElts[i].getPlainType()))); + } + return args; } /// Emit a raw apply operation, performing no additional lowering of @@ -2599,27 +2609,25 @@ namespace { /// arguments are going into a varargs array. struct ArgSpecialDest { VarargsInfo *SharedInfo; - unsigned Index : 31; - unsigned IsExpansion : 1; + unsigned Index : 32; CleanupHandle Cleanup; ArgSpecialDest() : SharedInfo(nullptr) {} - explicit ArgSpecialDest(VarargsInfo &info, unsigned index, bool isExpansion) - : SharedInfo(&info), Index(index), IsExpansion(isExpansion) {} + explicit ArgSpecialDest(VarargsInfo &info, unsigned index) + : SharedInfo(&info), Index(index) {} // Reference semantics: need to preserve the cleanup handle. ArgSpecialDest(const ArgSpecialDest &) = delete; ArgSpecialDest &operator=(const ArgSpecialDest &) = delete; ArgSpecialDest(ArgSpecialDest &&other) : SharedInfo(other.SharedInfo), Index(other.Index), - IsExpansion(other.IsExpansion), Cleanup(other.Cleanup) { + Cleanup(other.Cleanup) { other.SharedInfo = nullptr; } ArgSpecialDest &operator=(ArgSpecialDest &&other) { assert(!isValid() && "overwriting valid special destination!"); SharedInfo = other.SharedInfo; Index = other.Index; - IsExpansion = other.IsExpansion; Cleanup = other.Cleanup; other.SharedInfo = nullptr; return *this; @@ -2638,14 +2646,6 @@ struct ArgSpecialDest { SILType loweredSubstParamType) { assert(isValid() && "filling an invalid destination"); - if (IsExpansion) { - auto expr = std::move(arg).asKnownExpr()->getSemanticsProvidingExpr(); - auto array = cast(expr)->getSubExpr(); - SharedInfo->setExpansion(Index, SGF.emitRValueAsSingleValue(array)); - Cleanup = CleanupHandle::invalid(); - return; - } - SILLocation loc = arg.getLocation(); auto destAddr = SharedInfo->getBaseAddress(); if (Index != 0) { @@ -2719,51 +2719,6 @@ class ArgEmitter { maybeEmitForeignErrorArgument(); } - // origFormalType is a function type. - // - // FIXME: This is all a bunch of hacks that can be removed once "scalar" - // PreparedArguments goes away. - void emitTopLevel(ArgumentSource &&arg, AbstractionPattern origFormalType) { - SmallVector origParamTypes; - for (unsigned i = 0, e = origFormalType.getNumFunctionParams(); i < e; ++i) { - origParamTypes.push_back(origFormalType.getFunctionParamType(i)); - } - - auto origParamType = AbstractionPattern::getTuple(origParamTypes); - - if (arg.isShuffle()) { - auto *shuffle = cast(std::move(arg).asKnownExpr()); - emitShuffle(shuffle, origParamType); - maybeEmitForeignErrorArgument(); - return; - } - - if (arg.isLValue()) { - assert(origParamTypes.size() == 1); - emitSingleArg(std::move(arg), origParamTypes[0]); - return; - } - - if (arg.isExpr()) { - if (origParamTypes.size() == 1) { - auto *e = std::move(arg).asKnownExpr(); - - origParamType = origParamTypes[0]; - if (auto *paren = dyn_cast(e)) - e = paren->getSubExpr(); - else if (auto *tuple = dyn_cast(e)) { - assert(tuple->getNumElements() == 1); - e = tuple->getElement(0); - } - - emitSingleArg(e, origParamType); - return; - } - } - - emitSingleArg(std::move(arg), origParamType); - } - // origFormalType is a function type. void emitPreparedArgs(PreparedArguments &&args, AbstractionPattern origFormalType) { @@ -2772,8 +2727,20 @@ class ArgEmitter { if (args.isScalar()) { assert(argSources.size() == 1); - emitTopLevel(std::move(argSources[0]), origFormalType); + auto arg = std::move(argSources[0]); + auto *shuffle = cast(std::move(arg).asKnownExpr()); + + SmallVector origParamTypes; + for (unsigned i = 0, e = origFormalType.getNumFunctionParams(); i < e; ++i) { + origParamTypes.push_back(origFormalType.getFunctionParamType(i)); + } + + auto origParamType = AbstractionPattern::getTuple(origParamTypes); + + emitShuffle(shuffle, origParamType); + maybeEmitForeignErrorArgument(); } else { + maybeEmitForeignErrorArgument(); for (auto i : indices(argSources)) { emitSingleArg(std::move(argSources[i]), origFormalType.getFunctionParamType(i)); @@ -3473,9 +3440,8 @@ struct ElementExtent { ClaimedParamsRef Params; /// The destination index, if any. /// This is set in the first pass. - unsigned DestIndex : 29; + unsigned DestIndex : 30; unsigned HasDestIndex : 1; - unsigned IsVarargExpansion : 1; #ifndef NDEBUG unsigned Used : 1; #endif @@ -3520,7 +3486,6 @@ class ArgumentShuffleEmitter { /// Extents of the inner elements. SmallVector innerExtents; Optional varargsInfo; - SmallVector varargExpansions; SILParameterInfo variadicParamInfo; // innerExtents will point at this Optional> innerSpecialDests; @@ -3575,18 +3540,6 @@ class ArgumentShuffleEmitter { assert(!isResultScalar || index == 0); return origParamType.getTupleElementType(index); } - - VarargExpansionExpr *getVarargExpansion(unsigned innerIndex) { - Expr *expr = inner->getSemanticsProvidingExpr(); - if (cast(outer)->isSourceScalar()) { - assert(innerIndex == 0); - } else { - auto tuple = dyn_cast(expr); - if (!tuple) return nullptr; - expr = tuple->getElement(innerIndex)->getSemanticsProvidingExpr(); - } - return dyn_cast(expr); - } }; } // end anonymous namespace @@ -3635,22 +3588,10 @@ void ArgumentShuffleEmitter::constructInnerTupleTypeInfo(ArgEmitter &parent) { unsigned numVarargs = variadicArgs.size(); assert(canVarargsArrayType == substEltType); - // Check for vararg expansions, since their presence changes our - // emission strategy. - { - for (auto i : indices(variadicArgs)) { - unsigned innerIndex = variadicArgs[i]; - if (getVarargExpansion(innerIndex)) { - varargExpansions.push_back(i); - } - } - } - // If we don't have any vararg expansions, eagerly emit into // the array value. varargsInfo.emplace(emitBeginVarargs(parent.SGF, outer, varargsEltType, - canVarargsArrayType, numVarargs, - varargExpansions)); + canVarargsArrayType, numVarargs)); // If we have any varargs, we'll need to actually initialize // the array buffer. @@ -3679,12 +3620,9 @@ void ArgumentShuffleEmitter::constructInnerTupleTypeInfo(ArgEmitter &parent) { innerExtents[innerIndex].Used = true; #endif - auto expansion = getVarargExpansion(innerIndex); - // Set the destination index. innerExtents[innerIndex].HasDestIndex = true; innerExtents[innerIndex].DestIndex = i++; - innerExtents[innerIndex].IsVarargExpansion = (expansion != nullptr); // Use the singleton param info we prepared before. innerExtents[innerIndex].Params = @@ -3714,8 +3652,7 @@ void ArgumentShuffleEmitter::flattenPatternFromInnerExtendIntoInnerParams( if (extent.HasDestIndex) { assert(extent.Params.size() == 1); innerSpecialDests->push_back( - ArgSpecialDest(*varargsInfo, extent.DestIndex, - extent.IsVarargExpansion)); + ArgSpecialDest(*varargsInfo, extent.DestIndex)); // Otherwise, fill in with the appropriate number of invalid // special dests. @@ -4064,20 +4001,6 @@ class CallSite { bool Throws; public: - CallSite(ApplyExpr *apply) - : Loc(apply), SubstResultType(apply->getType()->getCanonicalType()), - Throws(apply->throws()) { - Expr *arg = apply->getArg(); - - 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); - } - CallSite(SILLocation loc, PreparedArguments &&args, CanType resultType, bool throws) : Loc(loc), SubstResultType(resultType), Args(std::move(args)), @@ -4085,30 +4008,6 @@ class CallSite { assert(Args.isValid()); } - // FIXME: Remove this entry point or refactor it so that isScalar is always - // false. - CallSite(SILLocation loc, ArgumentSource &&value, bool isScalar, - CanType resultType, bool 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, isScalar); - Args.addArbitrary(std::move(value)); - assert(Args.isValid()); - } - - CallSite(SILLocation loc, ArgumentSource &&value, bool isScalar, - CanAnyFunctionType fnType) - : CallSite(loc, std::move(value), isScalar, - fnType.getResult(), fnType->throws()) {} - - CallSite(SILLocation loc, PreparedArguments &&args, CanAnyFunctionType fnType) - : CallSite(loc, std::move(args), fnType.getResult(), fnType->throws()) {} - /// Return the substituted, unlowered AST parameter types of the argument. ArrayRef getParams() const { return Args.getParams(); } @@ -4135,9 +4034,8 @@ class CallSite { } /// Take the arguments for special processing, in place of the above. - ArgumentSource &&forward() && { - assert(Args.isScalar()); - return std::move(std::move(Args).getSources()[0]); + PreparedArguments &&forward() && { + return std::move(Args); } }; @@ -4180,7 +4078,7 @@ class CallEmission { /// A factory method for decomposing the apply expr \p e into a call /// emission. - static CallEmission forApplyExpr(SILGenFunction &SGF, Expr *e); + static CallEmission forApplyExpr(SILGenFunction &SGF, ApplyExpr *e); /// Add a level of function application by passing in its possibly /// unevaluated arguments and their formal type. @@ -4202,6 +4100,17 @@ class CallEmission { addCallSite(CallSite{std::forward(args)...}); } + void addSelfParam(SILLocation loc, + ArgumentSource &&selfArg, + AnyFunctionType::Param selfParam, + CanType methodType) { + PreparedArguments preparedSelf({selfParam}); + preparedSelf.addArbitrary(std::move(selfArg)); + + addCallSite(loc, std::move(preparedSelf), methodType, + /*throws*/ false); + } + /// Is this a fully-applied enum element constructor call? bool isEnumElementConstructor() { return (callee.kind == Callee::Kind::EnumElement && @@ -4523,6 +4432,12 @@ CallEmission::applyNormalCall(SGFContext C) { return firstLevelResult; } +static void emitPseudoFunctionArguments(SILGenFunction &SGF, + AbstractionPattern origFnType, + CanFunctionType substFnType, + SmallVectorImpl &outVals, + PreparedArguments &&args); + CallEmission::FirstLevelApplicationResult CallEmission::applyEnumElementConstructor(SGFContext C) { FirstLevelApplicationResult firstLevelResult; @@ -4547,9 +4462,15 @@ CallEmission::applyEnumElementConstructor(SGFContext C) { CanType formalResultType = firstLevelResult.formalType.getResult(); // Ignore metatype argument + SmallVector metatypeVal; + emitPseudoFunctionArguments(SGF, + AbstractionPattern(firstLevelResult.formalType), + firstLevelResult.formalType, metatypeVal, + std::move(uncurriedSites[0]).forward()); + assert(metatypeVal.size() == 1); + origFormalType = origFormalType.getFunctionResultType(); claimNextParamClause(firstLevelResult.formalType); - std::move(uncurriedSites[0]).forward().getAsSingleValue(SGF); // Get the payload argument. ArgumentSource payload; @@ -4557,8 +4478,16 @@ CallEmission::applyEnumElementConstructor(SGFContext C) { assert(uncurriedSites.size() == 2); SmallVector argVals; auto resultFnType = cast(formalResultType); - auto arg = SGF.prepareEnumPayload(element, resultFnType, - std::move(uncurriedSites[1]).forward()); + + emitPseudoFunctionArguments(SGF, + AbstractionPattern(resultFnType), + resultFnType, argVals, + std::move(uncurriedSites[1]).forward()); + + auto payloadTy = AnyFunctionType::composeInput(SGF.getASTContext(), + resultFnType.getParams(), + /*canonicalVararg*/ true); + auto arg = RValue(SGF, argVals, payloadTy->getCanonicalType()); payload = ArgumentSource(element, std::move(arg)); formalResultType = firstLevelResult.formalType.getResult(); origFormalType = origFormalType.getFunctionResultType(); @@ -4680,10 +4609,10 @@ CallEmission::applySpecializedEmitter(SpecializedEmitter &specializedEmitter, // We should be able to enforce that these arguments are // always still expressions. - Expr *argument = std::move(uncurriedSites[0]).forward().asKnownExpr(); + PreparedArguments args = std::move(uncurriedSites[0]).forward(); ManagedValue resultMV = emitter(SGF, uncurriedLoc, callee.getSubstitutions(), - argument, uncurriedContext); + std::move(args), uncurriedContext); firstLevelResult.value = RValue(SGF, uncurriedLoc, formalResultType, resultMV); return firstLevelResult; @@ -4869,7 +4798,7 @@ RValue CallEmission::applyRemainingCallSites(RValue &&result, return std::move(result); } -CallEmission CallEmission::forApplyExpr(SILGenFunction &SGF, Expr *e) { +CallEmission CallEmission::forApplyExpr(SILGenFunction &SGF, ApplyExpr *e) { // Set up writebacks for the call(s). FormalEvaluationScope writebacks(SGF); @@ -4889,16 +4818,32 @@ CallEmission CallEmission::forApplyExpr(SILGenFunction &SGF, Expr *e) { // Apply 'self' if provided. if (apply.selfParam) { - emission.addCallSite(RegularLocation(e), - std::move(apply.selfParam), /*scalar*/ false, - apply.selfType->getCanonicalType(), /*throws*/ false); + AnyFunctionType::Param selfParam( + apply.selfParam.getSubstRValueType(), + Identifier(), + apply.selfParam.isLValue() + ? ParameterTypeFlags().withInOut(true) + : ParameterTypeFlags()); + emission.addSelfParam(e, std::move(apply.selfParam), selfParam, + apply.selfType->getCanonicalType()); } // Apply arguments from call sites, innermost to outermost. for (auto site = apply.callSites.rbegin(), end = apply.callSites.rend(); site != end; ++site) { - emission.addCallSite(*site); + ApplyExpr *apply = *site; + + Expr *arg = apply->getArg(); + + SmallVector params; + AnyFunctionType::decomposeInput(arg->getType(), params); + + PreparedArguments preparedArgs(params, arg); + + emission.addCallSite(apply, std::move(preparedArgs), + apply->getType()->getCanonicalType(), + apply->throws()); } return emission; @@ -5374,7 +5319,7 @@ ManagedValue SILGenFunction::emitInjectEnum(SILLocation loc, }); } -RValue SILGenFunction::emitApplyExpr(Expr *e, SGFContext c) { +RValue SILGenFunction::emitApplyExpr(ApplyExpr *e, SGFContext c) { CallEmission emission = CallEmission::forApplyExpr(*this, e); return emission.apply(c); } @@ -5433,7 +5378,7 @@ getMagicFunctionString(SILGenFunction &SGF) { /// Emit an application of the given allocating initializer. RValue SILGenFunction::emitApplyAllocatingInitializer(SILLocation loc, ConcreteDeclRef init, - RValue &&args, + PreparedArguments &&args, Type overriddenSelfType, SGFContext C) { ConstructorDecl *ctor = cast(init.getDecl()); @@ -5493,36 +5438,32 @@ RValue SILGenFunction::emitApplyAllocatingInitializer(SILLocation loc, auto substFormalType = callee->getSubstFormalType(); - // For an inheritable initializer, determine whether we'll need to adjust the - // result type. - bool requiresDowncast = false; - if (ctor->isRequired() && overriddenSelfType) { - CanType substResultType = substFormalType; - substResultType = cast(substResultType).getResult(); - substResultType = cast(substResultType).getResult(); - - if (!substResultType->isEqual(overriddenSelfType)) - requiresDowncast = true; - } - // Form the call emission. CallEmission emission(*this, std::move(*callee), std::move(writebackScope)); + auto methodType = cast(substFormalType.getResult()); + auto resultType = methodType.getResult(); + // Self metatype. - emission.addCallSite(loc, - ArgumentSource(loc, - RValue(*this, loc, - selfMetaVal.getType() - .getASTType(), - std::move(selfMetaVal))), - /*scalar*/ false, - substFormalType); + emission.addSelfParam(loc, + ArgumentSource(loc, + RValue(*this, loc, + selfMetaVal.getType() + .getASTType(), + std::move(selfMetaVal))), + substFormalType.getParams()[0], + methodType); // Arguments. - // FIXME: Rework this so that scalar=false. - emission.addCallSite(loc, - ArgumentSource(loc, std::move(args)), /*scalar*/ true, - cast(substFormalType.getResult())); + emission.addCallSite(loc, std::move(args), resultType, /*throws*/ false); + + // For an inheritable initializer, determine whether we'll need to adjust the + // result type. + bool requiresDowncast = false; + if (ctor->isRequired() && overriddenSelfType) { + if (!resultType->isEqual(overriddenSelfType)) + requiresDowncast = true; + } // Perform the call. RValue result = emission.apply(requiresDowncast ? SGFContext() : C); @@ -5544,7 +5485,7 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) { ConcreteDeclRef builtinInit; ConcreteDeclRef init; // Emit the raw, builtin literal arguments. - RValue builtinLiteralArgs; + PreparedArguments builtinLiteralArgs; if (auto stringLiteral = dyn_cast(literal)) { builtinLiteralArgs = emitStringLiteral(*this, literal, stringLiteral->getValue(), C, @@ -5552,7 +5493,7 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) { builtinInit = stringLiteral->getBuiltinInitializer(); init = stringLiteral->getInitializer(); } else if (auto nilLiteral = dyn_cast(literal)) { - builtinLiteralArgs = emitEmptyTupleRValue(literal, C); + builtinLiteralArgs.emplace({}); builtinInit = nilLiteral->getInitializer(); } else if (auto booleanLiteral = dyn_cast(literal)) { auto i1Ty = SILType::getBuiltinIntegerType(1, getASTContext()); @@ -5560,7 +5501,8 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) { booleanLiteral->getValue()); ManagedValue boolManaged = ManagedValue::forUnmanaged(boolValue); CanType ty = boolManaged.getType().getASTType()->getCanonicalType(); - builtinLiteralArgs = RValue(*this, {boolManaged}, ty); + builtinLiteralArgs.emplace(AnyFunctionType::Param(ty)); + builtinLiteralArgs.add(literal, RValue(*this, {boolManaged}, ty)); builtinInit = booleanLiteral->getBuiltinInitializer(); init = booleanLiteral->getInitializer(); } else if (auto integerLiteral = dyn_cast(literal)) { @@ -5570,7 +5512,8 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) { SILType::getBuiltinIntegerLiteralType(getASTContext()), integerLiteral->getRawValue())); CanType ty = integerManaged.getType().getASTType(); - builtinLiteralArgs = RValue(*this, {integerManaged}, ty); + builtinLiteralArgs.emplace(AnyFunctionType::Param(ty)); + builtinLiteralArgs.add(literal, RValue(*this, {integerManaged}, ty)); builtinInit = integerLiteral->getBuiltinInitializer(); init = integerLiteral->getInitializer(); } else if (auto floatLiteral = dyn_cast(literal)) { @@ -5581,7 +5524,8 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) { floatLiteral->getValue())); CanType ty = floatManaged.getType().getASTType(); - builtinLiteralArgs = RValue(*this, {floatManaged}, ty); + builtinLiteralArgs.emplace(AnyFunctionType::Param(ty)); + builtinLiteralArgs.add(literal, RValue(*this, {floatManaged}, ty)); builtinInit = floatLiteral->getBuiltinInitializer(); init = floatLiteral->getInitializer(); } else { @@ -5622,10 +5566,12 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) { : ctx.SourceMgr.getLineAndColumn(Loc).second; } - auto Ty = SILType::getBuiltinIntegerLiteralType(ctx); - SILValue V = B.createIntegerLiteral(literal, Ty, Value); - builtinLiteralArgs = RValue(*this, {ManagedValue::forUnmanaged(V)}, - Ty.getASTType()->getCanonicalType()); + auto silTy = SILType::getBuiltinIntegerLiteralType(ctx); + auto ty = silTy.getASTType(); + SILValue integer = B.createIntegerLiteral(literal, silTy, Value); + ManagedValue integerManaged = ManagedValue::forUnmanaged(integer); + builtinLiteralArgs.emplace(AnyFunctionType::Param(ty)); + builtinLiteralArgs.add(literal, RValue(*this, {integerManaged}, ty)); builtinInit = magicLiteral->getBuiltinInitializer(); init = magicLiteral->getInitializer(); break; @@ -5646,8 +5592,12 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) { if (!init) return builtinLiteral; // Otherwise, perform the second initialization step. + auto ty = builtinLiteral.getType(); + PreparedArguments args((AnyFunctionType::Param(ty))); + args.add(literal, std::move(builtinLiteral)); + RValue result = emitApplyAllocatingInitializer(literal, init, - std::move(builtinLiteral), + std::move(args), literal->getType(), C); return result; } @@ -6022,9 +5972,10 @@ static void collectFakeIndexParameters(SILGenFunction &SGF, } static void emitPseudoFunctionArguments(SILGenFunction &SGF, + AbstractionPattern origFnType, CanFunctionType substFnType, SmallVectorImpl &outVals, - ArgumentSource &&source) { + PreparedArguments &&args) { auto substParams = substFnType->getParams(); SmallVector substParamTys; @@ -6042,7 +5993,7 @@ static void emitPseudoFunctionArguments(SILGenFunction &SGF, argValues, delayedArgs, /*foreign error*/ None, ImportAsMemberStatus()); - emitter.emitTopLevel(std::move(source), AbstractionPattern(substFnType)); + emitter.emitPreparedArgs(std::move(args), origFnType); // TODO: do something to preserve LValues in the delayed arguments? if (!delayedArgs.empty()) @@ -6074,12 +6025,22 @@ SILGenFunction::prepareSubscriptIndices(SubscriptDecl *subscript, substFnType = cast(interfaceType ->getCanonicalType()); + + AbstractionPattern origFnType(substFnType); + + // Prepare the unevaluated index expression. auto substParams = substFnType->getParams(); + PreparedArguments args(substParams, indexExpr); + // Now, force it to be evaluated. SmallVector argValues; - emitPseudoFunctionArguments(*this, substFnType, argValues, indexExpr); + emitPseudoFunctionArguments(*this, origFnType, substFnType, + argValues, std::move(args)); - PreparedArguments result(substParams, /*isScalar=*/false); + // Finally, prepare the evaluated index expression. We might be calling + // the getter and setter, and it is important to only evaluate the + // index expression once. + PreparedArguments result(substParams); ArrayRef remainingArgs = argValues; for (auto substParam : substParams) { @@ -6095,19 +6056,6 @@ SILGenFunction::prepareSubscriptIndices(SubscriptDecl *subscript, return result; } -RValue -SILGenFunction::prepareEnumPayload(EnumElementDecl *element, - CanFunctionType substFnType, - ArgumentSource &&args) { - SmallVector argValues; - emitPseudoFunctionArguments(*this, substFnType, argValues, std::move(args)); - - auto payloadTy = AnyFunctionType::composeInput(getASTContext(), - substFnType.getParams(), - /*canonicalVararg*/ true); - return RValue(*this, argValues, payloadTy->getCanonicalType()); -} - SILDeclRef SILGenModule::getAccessorDeclRef(AccessorDecl *accessor) { return SILDeclRef(accessor, SILDeclRef::Kind::Func) .asForeign(requiresForeignEntryPoint(accessor)); @@ -6132,15 +6080,18 @@ RValue SILGenFunction::emitGetAccessor(SILLocation loc, SILDeclRef get, CallEmission emission(*this, std::move(getter), std::move(writebackScope)); // Self -> if (hasSelf) { - emission.addCallSite(loc, std::move(selfValue), /*scalar*/ false, - accessType); + emission.addSelfParam(loc, std::move(selfValue), + accessType.getParams()[0], + accessType.getResult()); accessType = cast(accessType.getResult()); } // Index or () if none. if (subscriptIndices.isNull()) - subscriptIndices.emplaceEmptyArgumentList(*this); + subscriptIndices.emplace({}); - emission.addCallSite(loc, std::move(subscriptIndices), accessType); + emission.addCallSite(loc, std::move(subscriptIndices), + accessType.getResult(), + accessType->throws()); // T return emission.apply(c); @@ -6165,13 +6116,14 @@ void SILGenFunction::emitSetAccessor(SILLocation loc, SILDeclRef set, CallEmission emission(*this, std::move(setter), std::move(writebackScope)); // Self -> if (hasSelf) { - emission.addCallSite(loc, std::move(selfValue), /*scalar*/ false, - accessType); + emission.addSelfParam(loc, std::move(selfValue), + accessType.getParams()[0], + accessType.getResult()); accessType = cast(accessType.getResult()); } // (value) or (value, indices...) - PreparedArguments values(accessType->getParams(), /*scalar*/ false); + PreparedArguments values(accessType->getParams()); values.addArbitrary(std::move(setValue)); if (!subscriptIndices.isNull()) { @@ -6182,7 +6134,9 @@ void SILGenFunction::emitSetAccessor(SILLocation loc, SILDeclRef set, } } assert(values.isValid()); - emission.addCallSite(loc, std::move(values), accessType); + emission.addCallSite(loc, std::move(values), + accessType.getResult(), + accessType->throws()); // () emission.apply(); } @@ -6207,15 +6161,18 @@ ManagedValue SILGenFunction::emitAddressorAccessor( CallEmission emission(*this, std::move(callee), std::move(writebackScope)); // Self -> if (hasSelf) { - emission.addCallSite(loc, std::move(selfValue), /*scalar*/ false, - accessType); + emission.addSelfParam(loc, std::move(selfValue), + accessType.getParams()[0], + accessType.getResult()); accessType = cast(accessType.getResult()); } // Index or () if none. if (subscriptIndices.isNull()) - subscriptIndices.emplaceEmptyArgumentList(*this); + subscriptIndices.emplace({}); - emission.addCallSite(loc, std::move(subscriptIndices), accessType); + emission.addCallSite(loc, std::move(subscriptIndices), + accessType.getResult(), + accessType->throws()); // Unsafe{Mutable}Pointer or // (Unsafe{Mutable}Pointer, Builtin.UnknownPointer) or @@ -6269,15 +6226,18 @@ SILGenFunction::emitCoroutineAccessor(SILLocation loc, SILDeclRef accessor, CallEmission emission(*this, std::move(callee), std::move(writebackScope)); // Self -> if (hasSelf) { - emission.addCallSite(loc, std::move(selfValue), /*scalar*/ false, - accessType); + emission.addSelfParam(loc, std::move(selfValue), + accessType.getParams()[0], + accessType.getResult()); accessType = cast(accessType.getResult()); } // Index or () if none. if (subscriptIndices.isNull()) - subscriptIndices.emplaceEmptyArgumentList(*this); + subscriptIndices.emplace({}); - emission.addCallSite(loc, std::move(subscriptIndices), accessType); + emission.addCallSite(loc, std::move(subscriptIndices), + accessType.getResult(), + accessType->throws()); auto endApplyHandle = emission.applyCoroutine(yields); diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp index a5770c09dedd5..d2b0e78608942 100644 --- a/lib/SILGen/SILGenBuiltin.cpp +++ b/lib/SILGen/SILGenBuiltin.cpp @@ -12,6 +12,7 @@ #include "SpecializedEmitter.h" +#include "ArgumentSource.h" #include "Cleanup.h" #include "Initialization.h" #include "LValue.h" @@ -45,42 +46,40 @@ static bool isTrivialShuffle(ArgumentShuffleExpr *shuffle) { /// /// Because these are builtin operations, we can make some structural /// assumptions about the expression used to call them. -static ArrayRef decomposeArguments(SILGenFunction &SGF, - Expr *arg, - unsigned expectedCount) { - assert(expectedCount >= 2); - assert(arg->getType()->is()); - assert(arg->getType()->castTo()->getNumElements() - == expectedCount); - - // The use of owned parameters can trip up CSApply enough to introduce - // a trivial tuple shuffle here. - arg = arg->getSemanticsProvidingExpr(); - if (auto shuffle = dyn_cast(arg)) { - if (isTrivialShuffle(shuffle)) - arg = shuffle->getSubExpr(); - } +static Optional> +decomposeArguments(SILGenFunction &SGF, + SILLocation loc, + PreparedArguments &&args, + unsigned expectedCount) { + SmallVector result; + auto sources = std::move(args).getSources(); + + if (sources.size() == expectedCount) { + for (auto &&source : sources) + result.push_back(std::move(source).asKnownExpr()); + return result; + } else if (sources.size() == 1) { + auto *arg = std::move(sources[0]).asKnownExpr(); + + // The use of owned parameters can trip up CSApply enough to introduce + // a trivial tuple shuffle here. + if (auto shuffle = dyn_cast(arg)) { + if (isTrivialShuffle(shuffle)) + arg = shuffle->getSubExpr(); + } - auto tuple = dyn_cast(arg); - if (tuple && tuple->getElements().size() == expectedCount) { - return tuple->getElements(); + auto tuple = dyn_cast(arg); + if (tuple && tuple->getElements().size() == expectedCount) { + for (auto elt : tuple->getElements()) + result.push_back(elt); + return result; + } } - SGF.SGM.diagnose(arg, diag::invalid_sil_builtin, + SGF.SGM.diagnose(loc, diag::invalid_sil_builtin, "argument to builtin should be a literal tuple"); - auto tupleTy = arg->getType()->castTo(); - - // This is well-typed but may cause code to be emitted redundantly. - auto &ctxt = SGF.getASTContext(); - SmallVector args; - for (auto index : indices(tupleTy->getElementTypes())) { - Expr *projection = new (ctxt) TupleElementExpr(arg, SourceLoc(), - index, SourceLoc(), - tupleTy->getElementType(index)); - args.push_back(projection); - } - return ctxt.AllocateCopy(args); + return None; } static ManagedValue emitBuiltinRetain(SILGenFunction &SGF, @@ -252,9 +251,13 @@ static ManagedValue emitBuiltinAssign(SILGenFunction &SGF, static ManagedValue emitBuiltinInit(SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions, - Expr *tuple, + PreparedArguments &&preparedArgs, SGFContext C) { - auto args = decomposeArguments(SGF, tuple, 2); + auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 2); + if (!argsOrError) + return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc)); + + auto args = *argsOrError; CanType formalType = substitutions.getReplacementTypes()[0]->getCanonicalType(); @@ -421,23 +424,29 @@ static ManagedValue emitBuiltinBridgeFromRawPointer(SILGenFunction &SGF, static ManagedValue emitBuiltinAddressOf(SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions, - Expr *argument, + PreparedArguments &&preparedArgs, SGFContext C) { - auto rawPointerTy = SILType::getRawPointerType(SGF.getASTContext()); + SILType rawPointerType = SILType::getRawPointerType(SGF.getASTContext()); + + auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 1); + if (!argsOrError) + return SGF.emitUndef(rawPointerType); + + auto argument = (*argsOrError)[0]; + // If the argument is inout, try forming its lvalue. This builtin only works // if it's trivially physically projectable. auto inout = cast(argument->getSemanticsProvidingExpr()); auto lv = SGF.emitLValue(inout->getSubExpr(), SGFAccessKind::ReadWrite); if (!lv.isPhysical() || !lv.isLoadingPure()) { SGF.SGM.diagnose(argument->getLoc(), diag::non_physical_addressof); - return SGF.emitUndef(rawPointerTy); + return SGF.emitUndef(rawPointerType); } auto addr = SGF.emitAddressOfLValue(argument, std::move(lv)) .getLValueAddress(); // Take the address argument and cast it to RawPointer. - SILType rawPointerType = SILType::getRawPointerType(SGF.F.getASTContext()); SILValue result = SGF.B.createAddressToPointer(loc, addr, rawPointerType); return ManagedValue::forUnmanaged(result); @@ -447,9 +456,16 @@ static ManagedValue emitBuiltinAddressOf(SILGenFunction &SGF, static ManagedValue emitBuiltinAddressOfBorrow(SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions, - Expr *argument, + PreparedArguments &&preparedArgs, SGFContext C) { - auto rawPointerTy = SILType::getRawPointerType(SGF.getASTContext()); + SILType rawPointerType = SILType::getRawPointerType(SGF.getASTContext()); + + auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 1); + if (!argsOrError) + return SGF.emitUndef(rawPointerType); + + auto argument = (*argsOrError)[0]; + SILValue addr; // Try to borrow the argument at +0. We only support if it's // naturally emitted borrowed in memory. @@ -457,13 +473,12 @@ static ManagedValue emitBuiltinAddressOfBorrow(SILGenFunction &SGF, .getAsSingleValue(SGF, argument); if (!borrow.isPlusZero() || !borrow.getType().isAddress()) { SGF.SGM.diagnose(argument->getLoc(), diag::non_borrowed_indirect_addressof); - return SGF.emitUndef(rawPointerTy); + return SGF.emitUndef(rawPointerType); } addr = borrow.getValue(); // Take the address argument and cast it to RawPointer. - SILType rawPointerType = SILType::getRawPointerType(SGF.F.getASTContext()); SILValue result = SGF.B.createAddressToPointer(loc, addr, rawPointerType); return ManagedValue::forUnmanaged(result); diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index eb2aa66c410f2..b7dd79fd1cc4f 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -1858,26 +1858,33 @@ visitConditionalCheckedCastExpr(ConditionalCheckedCastExpr *E, trueCount, falseCount); } -RValue RValueEmitter::visitIsExpr(IsExpr *E, SGFContext C) { - SILValue isa = emitIsa(SGF, E, E->getSubExpr(), - E->getCastTypeLoc().getType(), E->getCastKind()); - +static RValue emitBoolLiteral(SILGenFunction &SGF, SILLocation loc, + SILValue builtinBool, + SGFContext C) { // Call the Bool(_builtinBooleanLiteral:) initializer ASTContext &ctx = SGF.getASTContext(); auto init = ctx.getBoolBuiltinInitDecl(); - Type builtinArgType = BuiltinIntegerType::get(1, ctx); - RValue builtinArg(SGF, ManagedValue::forUnmanaged(isa), - builtinArgType->getCanonicalType()); + auto builtinArgType = CanType(BuiltinIntegerType::get(1, ctx)); + RValue builtinArg(SGF, ManagedValue::forUnmanaged(builtinBool), + builtinArgType); + + PreparedArguments builtinArgs((AnyFunctionType::Param(builtinArgType))); + builtinArgs.add(loc, std::move(builtinArg)); + auto result = - SGF.emitApplyAllocatingInitializer(E, ConcreteDeclRef(init), - std::move(builtinArg), Type(), + SGF.emitApplyAllocatingInitializer(loc, ConcreteDeclRef(init), + std::move(builtinArgs), Type(), C); return result; } +RValue RValueEmitter::visitIsExpr(IsExpr *E, SGFContext C) { + SILValue isa = emitIsa(SGF, E, E->getSubExpr(), + E->getCastTypeLoc().getType(), E->getCastKind()); + return emitBoolLiteral(SGF, E, isa, C); +} RValue RValueEmitter::visitEnumIsCaseExpr(EnumIsCaseExpr *E, SGFContext C) { - ASTContext &ctx = SGF.getASTContext(); // Get the enum value. auto subExpr = SGF.emitRValueAsSingleValue(E->getSubExpr(), SGFContext(SGFContext::AllowImmediatePlusZero)); @@ -1895,16 +1902,7 @@ RValue RValueEmitter::visitEnumIsCaseExpr(EnumIsCaseExpr *E, {{E->getEnumElement(), t}}); } - // Call the Bool(_builtinBooleanLiteral:) initializer - auto init = ctx.getBoolBuiltinInitDecl(); - Type builtinArgType = BuiltinIntegerType::get(1, ctx); - RValue builtinArg(SGF, ManagedValue::forUnmanaged(selected), - builtinArgType->getCanonicalType()); - auto result = - SGF.emitApplyAllocatingInitializer(E, ConcreteDeclRef(init), - std::move(builtinArg), Type(), - C); - return result; + return emitBoolLiteral(SGF, E, selected, C); } RValue RValueEmitter::visitCoerceExpr(CoerceExpr *E, SGFContext C) { @@ -1916,20 +1914,11 @@ RValue RValueEmitter::visitCoerceExpr(CoerceExpr *E, SGFContext C) { VarargsInfo Lowering::emitBeginVarargs(SILGenFunction &SGF, SILLocation loc, CanType baseTy, CanType arrayTy, - unsigned numElements, - ArrayRef expansionIndices) { + unsigned numElements) { // Reabstract the base type against the array element type. auto baseAbstraction = AbstractionPattern::getOpaque(); auto &baseTL = SGF.getTypeLowering(baseAbstraction, baseTy); - if (!expansionIndices.empty()) { - // An assertion is okay here for now because this is only in generated code. - assert(numElements == 1 && - "expansion that is not the only variadic argument is unsupported"); - return VarargsInfo(ManagedValue(), CleanupHandle::invalid(), SILValue(), - baseTL, baseAbstraction, /*expansion peephole*/ true); - } - // Allocate the array. SILValue numEltsVal = SGF.B.createIntegerLiteral(loc, SILType::getBuiltinWordType(SGF.getASTContext()), @@ -1955,18 +1944,11 @@ VarargsInfo Lowering::emitBeginVarargs(SILGenFunction &SGF, SILLocation loc, /*isStrict*/ true, /*isInvariant*/ false); - return VarargsInfo(array, abortCleanup, basePtr, baseTL, baseAbstraction, - /*expansion peephole*/ false); + return VarargsInfo(array, abortCleanup, basePtr, baseTL, baseAbstraction); } ManagedValue Lowering::emitEndVarargs(SILGenFunction &SGF, SILLocation loc, VarargsInfo &&varargs) { - if (varargs.isExpansionPeephole()) { - auto result = varargs.getArray(); - assert(result); - return result; - } - // Kill the abort cleanup. SGF.Cleanups.setCleanupState(varargs.getAbortCleanup(), CleanupState::Dead); @@ -2432,7 +2414,7 @@ loadIndexValuesForKeyPathComponent(SILGenFunction &SGF, SILLocation loc, indexParams.emplace_back(SGF.F.mapTypeIntoContext(elt.first)); } - PreparedArguments indexValues(indexParams, /*scalar*/ indexes.size() == 1); + PreparedArguments indexValues(indexParams); if (indexes.empty()) { assert(indexValues.isValid()); return indexValues; @@ -3606,11 +3588,22 @@ RValue RValueEmitter::visitArrayExpr(ArrayExpr *E, SGFContext C) { auto loc = SILLocation(E); ArgumentScope scope(SGF, loc); - CanType elementType = E->getElementType()->getCanonicalType(); - CanType arrayTy = ArraySliceType::get(elementType)->getCanonicalType(); + // CSApply builds ArrayExprs without an initializer for the trivial case + // of emitting varargs. + CanType arrayType, elementType; + if (E->getInitializer()) { + elementType = E->getElementType()->getCanonicalType(); + arrayType = ArraySliceType::get(elementType)->getCanonicalType(); + } else { + arrayType = E->getType()->getCanonicalType(); + auto genericType = cast(arrayType); + assert(genericType->getDecl() == SGF.getASTContext().getArrayDecl()); + elementType = genericType.getGenericArgs()[0]; + } + VarargsInfo varargsInfo = - emitBeginVarargs(SGF, loc, elementType, arrayTy, - E->getNumElements(), {}); + emitBeginVarargs(SGF, loc, elementType, arrayType, + E->getNumElements()); // Cleanups for any elements that have been initialized so far. SmallVector cleanups; @@ -3644,19 +3637,22 @@ RValue RValueEmitter::visitArrayExpr(ArrayExpr *E, SGFContext C) { for (auto destCleanup : cleanups) SGF.Cleanups.setCleanupState(destCleanup, CleanupState::Dead); - RValue arg(SGF, loc, arrayTy, + RValue array(SGF, loc, arrayType, emitEndVarargs(SGF, loc, std::move(varargsInfo))); - arg = scope.popPreservingValue(std::move(arg)); + array = scope.popPreservingValue(std::move(array)); // If we're building an array, we don't have to call the initializer; // we've already built one. - if (arrayTy->isEqual(E->getType())) - return arg; + if (arrayType->isEqual(E->getType())) + return array; // Call the builtin initializer. + PreparedArguments args(AnyFunctionType::Param(E->getType())); + args.add(E, std::move(array)); + return SGF.emitApplyAllocatingInitializer( - loc, E->getInitializer(), std::move(arg), E->getType(), C); + loc, E->getInitializer(), std::move(args), E->getType(), C); } RValue RValueEmitter::visitDictionaryExpr(DictionaryExpr *E, SGFContext C) { diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h index d70276bf58917..84beec74a7057 100644 --- a/lib/SILGen/SILGenFunction.h +++ b/lib/SILGen/SILGenFunction.h @@ -1210,10 +1210,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction AccessStrategy strategy, Expr *indices); - RValue prepareEnumPayload(EnumElementDecl *element, - CanFunctionType substFnType, - ArgumentSource &&indexExpr); - ArgumentSource prepareAccessorBaseArg(SILLocation loc, ManagedValue base, CanType baseFormalType, SILDeclRef accessor); @@ -1417,7 +1413,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction // Helpers for emitting ApplyExpr chains. // - RValue emitApplyExpr(Expr *e, SGFContext c); + RValue emitApplyExpr(ApplyExpr *e, SGFContext c); /// Emit a function application, assuming that the arguments have been /// lowered appropriately for the abstraction level but that the @@ -1463,7 +1459,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction SGFContext ctx); RValue emitApplyAllocatingInitializer(SILLocation loc, ConcreteDeclRef init, - RValue &&args, Type overriddenSelfType, + PreparedArguments &&args, Type overriddenSelfType, SGFContext ctx); CleanupHandle emitBeginApply(SILLocation loc, ManagedValue fn, diff --git a/lib/SILGen/SpecializedEmitter.h b/lib/SILGen/SpecializedEmitter.h index c249b6a0aab76..7b591666a5746 100644 --- a/lib/SILGen/SpecializedEmitter.h +++ b/lib/SILGen/SpecializedEmitter.h @@ -32,6 +32,7 @@ class ManagedValue; class SGFContext; class SILGenFunction; class SILGenModule; +class PreparedArguments; /// Some kind of specialized emitter for a builtin function. class SpecializedEmitter { @@ -41,7 +42,7 @@ class SpecializedEmitter { using EarlyEmitter = ManagedValue (SILGenFunction &, SILLocation, SubstitutionMap, - Expr *argument, + PreparedArguments &&args, SGFContext); /// A special function for emitting a call after the arguments diff --git a/lib/SILGen/Varargs.h b/lib/SILGen/Varargs.h index b38df4e18981f..334b2baf9587c 100644 --- a/lib/SILGen/Varargs.h +++ b/lib/SILGen/Varargs.h @@ -35,23 +35,12 @@ class VarargsInfo { SILValue BaseAddress; AbstractionPattern BasePattern; const TypeLowering &BaseTL; - bool IsExpansionPeephole = false; public: VarargsInfo(ManagedValue array, CleanupHandle abortCleanup, SILValue baseAddress, const TypeLowering &baseTL, - AbstractionPattern basePattern, bool isExpansionPeephole) + AbstractionPattern basePattern) : Array(array), AbortCleanup(abortCleanup), - BaseAddress(baseAddress), BasePattern(basePattern), BaseTL(baseTL), - IsExpansionPeephole(isExpansionPeephole) {} - - void setExpansion(unsigned index, ManagedValue expansion) { - assert(IsExpansionPeephole); - assert(index == 0 && "non-initial index for peephole?"); - assert(!Array && "array already filled"); - Array = expansion; - } - - bool isExpansionPeephole() const { return IsExpansionPeephole; } + BaseAddress(baseAddress), BasePattern(basePattern), BaseTL(baseTL) {} /// Return the array value. emitEndVarargs() is really the only /// function that should be accessing this directly. @@ -75,8 +64,7 @@ class VarargsInfo { /// Begin a varargs emission sequence. VarargsInfo emitBeginVarargs(SILGenFunction &SGF, SILLocation loc, CanType baseTy, CanType arrayTy, - unsigned numElements, - ArrayRef expansions); + unsigned numElements); /// Successfully end a varargs emission sequence. ManagedValue emitEndVarargs(SILGenFunction &SGF, SILLocation loc, diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 6e6d0b83d35ce..8dc7b5cbd7474 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -2945,11 +2945,7 @@ namespace { Expr *visitVarargExpansionExpr(VarargExpansionExpr *expr) { simplifyExprType(expr); - auto elementTy = cs.getType(expr); - auto arrayTy = - cs.getTypeChecker().getArraySliceType(expr->getLoc(), elementTy); - if (!arrayTy) return expr; - + auto arrayTy = cs.getType(expr); expr->setSubExpr(coerceToType(expr->getSubExpr(), arrayTy, cs.getConstraintLocator(expr))); return expr; diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index b4a2805a6657f..77199a739f4e5 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1718,7 +1718,9 @@ namespace { for (unsigned i = 0, n = expr->getNumElements(); i != n; ++i) { auto *elt = expr->getElement(i); auto ty = CS.getType(elt); - auto flags = ParameterTypeFlags().withInOut(elt->isSemanticallyInOutExpr()); + auto flags = ParameterTypeFlags() + .withInOut(elt->isSemanticallyInOutExpr()) + .withVariadic(isa(elt)); elements.push_back(TupleTypeElt(ty->getInOutObjectType(), expr->getElementName(i), flags)); } @@ -2438,12 +2440,7 @@ namespace { CS.addConstraint(ConstraintKind::Conversion, CS.getType(expr->getSubExpr()), array, CS.getConstraintLocator(expr)); - - // The apparent type of the expression is the element type, as far as - // the type-checker is concerned. When this becomes a real feature, - // we should syntactically restrict these expressions to only appear - // in specific positions. - return element; + return array; } Type visitDynamicTypeExpr(DynamicTypeExpr *expr) { diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 8cb349f93fadb..f9ebb40adedcb 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -390,6 +390,13 @@ matchCallArguments(ArrayRef args, // Record the first argument for the variadic. parameterBindings[paramIdx].push_back(*claimed); + // If the argument is itself variadic, we're forwarding varargs + // with a VarargExpansionExpr; don't collect any more arguments. + if (args[*claimed].isVariadic()) { + skipClaimedArgs(); + return; + } + auto currentNextArgIdx = nextArgIdx; { nextArgIdx = *claimed; diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 55e7576c3bcf3..1770ba0307777 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -457,7 +457,8 @@ static Expr *buildArgumentForwardingExpr(ArrayRef params, } // A single unlabeled value is not a tuple. - if (args.size() == 1 && labels[0].empty()) { + if (args.size() == 1 && labels[0].empty() && + !isa(args[0])) { return new (ctx) ParenExpr(SourceLoc(), args[0], SourceLoc(), /*hasTrailingClosure=*/false); }