Skip to content
Draft
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
34 changes: 15 additions & 19 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -5117,23 +5117,19 @@ class SILResultInfo {
return getConvention() == ResultConvention::Pack;
}

bool isAddressResult(bool loweredAddresses) const {
if (loweredAddresses) {
return getConvention() == ResultConvention::GuaranteedAddress ||
getConvention() == ResultConvention::Inout;
}
return getConvention() == ResultConvention::Inout;
// Formal means after AddressLowering.
bool isFormalAddressResult() const {
return getConvention() == ResultConvention::GuaranteedAddress ||
getConvention() == ResultConvention::Inout;
}

bool isGuaranteedResult(bool loweredAddresses) const {
if (loweredAddresses) {
return getConvention() == ResultConvention::Guaranteed;
}
return getConvention() == ResultConvention::Guaranteed ||
getConvention() == ResultConvention::GuaranteedAddress;
// Formal means after AddressLowering.
bool isFormalGuaranteedResult() const {
return getConvention() == ResultConvention::Guaranteed;
}

bool isGuaranteedAddressResult() const {
// Formal means after AddressLowering.
bool isFormalGuaranteedAddressResult() const {
return getConvention() == ResultConvention::GuaranteedAddress;
}

Expand Down Expand Up @@ -5582,25 +5578,25 @@ class SILFunctionType final
return hasErrorResult() && getErrorResult().isFormalIndirect();
}

bool hasGuaranteedResult(bool loweredAddresses) const {
bool hasGuaranteedResult() const {
if (getNumResults() != 1) {
return false;
}
return getResults()[0].isGuaranteedResult(loweredAddresses);
return getSingleResult().isFormalGuaranteedResult();
}

bool hasAddressResult(bool loweredAddresses) const {
bool hasAddressResult() const {
if (getNumResults() != 1) {
return false;
}
return getResults()[0].isAddressResult(loweredAddresses);
return getSingleResult().isFormalAddressResult();
}

bool hasGuaranteedAddressResult() const {
if (getNumResults() != 1) {
return false;
}
return getResults()[0].isGuaranteedAddressResult();
return getSingleResult().isFormalGuaranteedAddressResult();
}

struct IndirectFormalResultFilter {
Expand Down Expand Up @@ -5646,7 +5642,7 @@ class SILFunctionType final
return llvm::make_filter_range(getResults(), PackResultFilter());
}

/// Get a single non-address SILType that represents all formal direct
/// Get a single SILType that represents all formal direct
/// results. The actual SIL result type of an apply instruction that calls
/// this function depends on the current SIL stage and is known by
/// SILFunctionConventions. It may be a wider tuple that includes formally
Expand Down
97 changes: 78 additions & 19 deletions include/swift/SIL/SILFunctionConventions.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ class SILModuleConventions {
static bool isIndirectSILResult(SILResultInfo result,
bool loweredAddresses);

static bool isAddressResult(SILResultInfo result,
bool loweredAddresses);

static bool isGuaranteedResult(SILResultInfo result,
bool loweredAddresses);

static SILType getSILParamInterfaceType(
SILParameterInfo yield,
bool loweredAddresses);
Expand Down Expand Up @@ -129,6 +135,14 @@ class SILModuleConventions {
return isIndirectSILResult(result, loweredAddresses);
}

bool isAddressResult(SILResultInfo result) const {
return isAddressResult(result, loweredAddresses);
}

bool isGuaranteedResult(SILResultInfo result) const {
return isGuaranteedResult(result, loweredAddresses);
}

SILType getSILType(SILParameterInfo param, CanSILFunctionType funcTy,
TypeExpansionContext context) const {
auto interfaceTy = getSILParamInterfaceType(param, loweredAddresses);
Expand Down Expand Up @@ -190,6 +204,10 @@ class SILFunctionConventions {
return silConv.isSILIndirect(result);
}

bool isAddressResult(SILResultInfo result) const {
return silConv.isAddressResult(result);
}

SILType getSILType(SILParameterInfo param,
TypeExpansionContext context) const {
return silConv.getSILType(param, funcTy, context);
Expand All @@ -213,8 +231,10 @@ class SILFunctionConventions {
if (silConv.loweredAddresses)
return funcTy->getDirectFormalResultsType(silConv.getModule(), context);

if (funcTy->hasAddressResult(silConv.loweredAddresses)) {
assert(funcTy->getNumDirectFormalResults() == 1);
// getAllResultsSubstType always returns an object-category SILType, but
// there are some result types that are addresses prior to AddressLowering.
if (funcTy->getNumResults() == 1 &&
silConv.isAddressResult(funcTy->getSingleResult())) {
return SILType::getPrimitiveAddressType(
funcTy->getSingleDirectFormalResult().getReturnValueType(
silConv.getModule(), funcTy, context));
Expand Down Expand Up @@ -330,34 +350,32 @@ class SILFunctionConventions {
if (funcTy->getNumResults() != 1) {
return false;
}
auto resultConvention = funcTy->getResults()[0].getConvention();
if (silConv.loweredAddresses) {
return resultConvention == ResultConvention::Guaranteed;
}
return resultConvention == ResultConvention::Guaranteed ||
resultConvention == ResultConvention::GuaranteedAddress;
return silConv.isGuaranteedResult(funcTy->getSingleResult());
}

bool hasAddressResult() const {
return hasGuaranteedAddressResult() || hasInoutResult();
if (funcTy->getNumResults() != 1) {
return false;
}
return silConv.isAddressResult(funcTy->getSingleResult());
}

// Prior to AddressLowering, this will return false, as "GuaranteedAddress"
// is not actually an address.
bool hasGuaranteedAddressResult() const {
if (funcTy->getNumResults() != 1) {
return false;
}
if (!silConv.loweredAddresses) {
return false;
}
auto resultConvention = funcTy->getResults()[0].getConvention();
return resultConvention == ResultConvention::GuaranteedAddress;
auto resultInfo = funcTy->getSingleResult();
return silConv.isAddressResult(resultInfo) &&
resultInfo.getConvention() == ResultConvention::GuaranteedAddress;
}

bool hasInoutResult() const {
if (funcTy->getNumResults() != 1) {
return false;
}
auto resultConvention = funcTy->getResults()[0].getConvention();
auto resultConvention = funcTy->getSingleResult().getConvention();
return resultConvention == ResultConvention::Inout;
}

Expand Down Expand Up @@ -710,6 +728,46 @@ inline bool SILModuleConventions::isIndirectSILResult(SILResultInfo result,
llvm_unreachable("Unhandled ResultConvention in switch.");
}

inline bool SILModuleConventions::isAddressResult(SILResultInfo result,
bool loweredAddresses) {
switch (result.getConvention()) {
case ResultConvention::Inout:
return true;
case ResultConvention::GuaranteedAddress:
return loweredAddresses;
case ResultConvention::Guaranteed:
case ResultConvention::Indirect:
case ResultConvention::Pack:
case ResultConvention::Owned:
case ResultConvention::Unowned:
case ResultConvention::UnownedInnerPointer:
case ResultConvention::Autoreleased:
return false;
}

llvm_unreachable("Unhandled ResultConvention in switch.");
}

inline bool SILModuleConventions::isGuaranteedResult(SILResultInfo result,
bool loweredAddresses) {
switch (result.getConvention()) {
case ResultConvention::Guaranteed:
return true;
case ResultConvention::GuaranteedAddress:
return !loweredAddresses;
case ResultConvention::Inout:
case ResultConvention::Indirect:
case ResultConvention::Pack:
case ResultConvention::Owned:
case ResultConvention::Unowned:
case ResultConvention::UnownedInnerPointer:
case ResultConvention::Autoreleased:
return false;
}

llvm_unreachable("Unhandled ResultConvention in switch.");
}

inline SILType SILModuleConventions::getSILParamInterfaceType(
SILParameterInfo param,
bool loweredAddresses) {
Expand All @@ -727,10 +785,11 @@ inline SILType SILModuleConventions::getSILYieldInterfaceType(
inline SILType
SILModuleConventions::getSILResultInterfaceType(SILResultInfo result,
bool loweredAddresses) {
return SILModuleConventions::isIndirectSILResult(result, loweredAddresses) ||
result.isAddressResult(loweredAddresses)
? SILType::getPrimitiveAddressType(result.getInterfaceType())
: SILType::getPrimitiveObjectType(result.getInterfaceType());
if (SILModuleConventions::isIndirectSILResult(result, loweredAddresses) ||
SILModuleConventions::isAddressResult(result, loweredAddresses)) {
return SILType::getPrimitiveAddressType(result.getInterfaceType());
}
return SILType::getPrimitiveObjectType(result.getInterfaceType());
}

inline SILType
Expand Down
2 changes: 1 addition & 1 deletion lib/IRGen/LoadableByAddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2848,7 +2848,7 @@ void LoadableByAddress::recreateSingleApply(
if ((isa<ApplyInst>(applyInst) || isa<TryApplyInst>(applyInst)) &&
modNonFuncTypeResultType(genEnv, origSILFunctionType, *currIRMod) &&
modifiableApply(applySite, *getIRGenModule()) &&
!origSILFunctionType->hasGuaranteedResult(true)) {
!origSILFunctionType->hasGuaranteedResult()) {
assert(allApplyRetToAllocMap.find(applyInst) !=
allApplyRetToAllocMap.end());
auto newAlloc = allApplyRetToAllocMap.find(applyInst)->second;
Expand Down
13 changes: 6 additions & 7 deletions lib/SIL/IR/SILFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,6 @@ SILType
SILFunctionType::getDirectFormalResultsType(SILModule &M,
TypeExpansionContext context) {
CanType type;

if (hasAddressResult(SILModuleConventions(M).useLoweredAddresses())) {
assert(getNumDirectFormalResults() == 1);
return SILType::getPrimitiveAddressType(
getSingleDirectFormalResult().getReturnValueType(M, this, context));
}

if (getNumDirectFormalResults() == 0) {
type = getASTContext().TheEmptyTupleType;
} else if (getNumDirectFormalResults() == 1) {
Expand All @@ -208,6 +201,12 @@ SILFunctionType::getDirectFormalResultsType(SILModule &M,
cache = type;
}
}

if (hasAddressResult()) {
assert(getNumDirectFormalResults() == 1);
return SILType::getPrimitiveAddressType(type);
}

return SILType::getPrimitiveObjectType(type);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/SIL/IR/SILType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ SILResultInfo::getOwnershipKind(SILFunction &F,
return OwnershipKind::None;
return OwnershipKind::Unowned;
case ResultConvention::GuaranteedAddress:
return isAddressResult(SILModuleConventions(M).loweredAddresses)
return SILModuleConventions(M).isAddressResult(*this)
? OwnershipKind::None
: OwnershipKind::Guaranteed;
case ResultConvention::Inout:
Expand Down
9 changes: 9 additions & 0 deletions lib/SIL/IR/ValueOwnership.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,15 @@ static ValueOwnershipKind visitFullApplySite(FullApplySite fai,
if (isTrivial)
return OwnershipKind::None;

// If the result type is an address, avoid consulting SILFunctionConventions
// to determine its ownership; we know it's None.
//
// This short-cut is needed _during_ AddressLowering for a @guaranteed_address
// result, as a new ApplyInst it creates with an address result happens before
// the global lowered-addresses flag is changed to influence getOwnershipKind.
if (ResultType.isAddress())
return OwnershipKind::None;

SILFunctionConventions fnConv(fai.getSubstCalleeType(), f->getModule());
auto results = fnConv.getDirectSILResults();
// No results => None.
Expand Down
23 changes: 21 additions & 2 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5613,22 +5613,41 @@ ManagedValue CallEmission::applyBorrowMutateAccessor() {
// begin_borrow instructions added for move-only self argument.
if (selfArgMV.getValue()->getType().isMoveOnly() &&
selfArgMV.getValue()->getType().isObject()) {
uncurriedArgs.back() = ManagedValue::forBorrowedObjectRValue(
selfArgMV = ManagedValue::forBorrowedObjectRValue(
lookThroughMoveOnlyCheckerPattern(selfArgMV.getValue()));
}

// Under opaque values a borrow/mutate accessor's self parameter is lowered to
// a by-value object (a @guaranteed self for a borrow accessor), but the base
// can still be an address, e.g., the begin_access of an inout base.
// Load it so the argument matches the accessor's self convention.
if (!SGF.silConv.useLoweredAddresses() && selfArgMV.getType().isAddress()) {
SILFunctionConventions substConv(calleeTypeInfo.substFnType,
SGF.getModule());
auto selfParamTy = substConv.getSILType(
calleeTypeInfo.substFnType->getSelfParameter(),
SGF.getTypeExpansionContext());
if (selfParamTy.isObject()) {
selfArgMV =
SGF.emitManagedLoadBorrow(uncurriedLoc.value(), selfArgMV.getValue());
}
}

if (fnValue.getFunction()->getConventions().hasGuaranteedResult()) {
if (isa<LoadBorrowInst>(selfArgMV)) {
// unchecked_ownership is used to silence the ownership verifier for
// returning a value produced within a load_borrow scope. SILGenCleanup
// eliminates it and introduces return_borrow appropriately.
uncurriedArgs.back() =
selfArgMV =
ManagedValue::forForwardedRValue(
SGF, SGF.B.createUncheckedOwnership(uncurriedLoc.value(),
selfArgMV.getValue()));
}
}

// Write-back the self arg.
uncurriedArgs.back() = selfArgMV;

auto value = SGF.applyBorrowMutateAccessor(
uncurriedLoc.value(), fnValue, callee.getSubstitutions(),
uncurriedArgs, calleeTypeInfo.substFnType, options);
Expand Down
3 changes: 1 addition & 2 deletions lib/SILGen/SILGenPoly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3016,8 +3016,7 @@ forwardFunctionArguments(SILGenFunction &SGF, SILLocation loc,
if (isGuaranteedParameterInCallee(argTy.getConvention())) {
auto forwardedArg =
SGF.emitManagedBeginBorrow(loc, arg.getValue()).getValue();
if (forwardedArg->getType().isObject() &&
fTy->hasGuaranteedResult(/*loweredAddresses*/ true)) {
if (forwardedArg->getType().isObject() && fTy->hasGuaranteedResult()) {
forwardedArg = SGF.B.createUncheckedOwnership(loc, forwardedArg);
}
forwardedArgs.push_back(forwardedArg);
Expand Down
Loading