Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
7 changes: 6 additions & 1 deletion include/swift/AST/DeclAttr.def
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,12 @@ DECL_ATTR(specialized, Specialized,
AllowMultipleAttributes | LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
172)

LAST_DECL_ATTR(Specialized)
SIMPLE_DECL_ATTR(_unsafeSelfDependentResult, UnsafeSelfDependentResult,
OnAccessor,
UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIBreakingToRemove | EquivalentInABIAttr,
173)

LAST_DECL_ATTR(UnsafeSelfDependentResult)

#undef DECL_ATTR_ALIAS
#undef CONTEXTUAL_DECL_ATTR_ALIAS
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -8929,5 +8929,8 @@ ERROR(attr_inline_always_requires_inlinable,none,
ERROR(attr_inline_always_no_usable_from_inline,none,
"cannot use '@inline(always)' together with '@usableFromInline'", ())

ERROR(unsafe_self_dependent_result_attr_on_invalid_decl,none,
"invalid use of @_unsafeSelfDependentResult", ())

#define UNDEFINE_DIAGNOSTIC_MACROS
#include "DefineDiagnosticMacros.h"
7 changes: 7 additions & 0 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -5410,6 +5410,13 @@ class SILFunctionType final
return hasErrorResult() && getErrorResult().isFormalIndirect();
}

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

bool hasGuaranteedAddressResult() const {
if (getNumResults() != 1) {
return false;
Expand Down
2 changes: 2 additions & 0 deletions include/swift/SIL/InstructionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ SILValue stripCastsWithoutMarkDependence(SILValue V);
/// begin_borrow instructions.
SILValue lookThroughOwnershipInsts(SILValue v);

SILValue lookThroughMoveOnlyCheckerPattern(SILValue value);

/// Reverse of lookThroughOwnershipInsts.
///
/// Return true if \p visitor returned true for all uses.
Expand Down
8 changes: 5 additions & 3 deletions include/swift/SIL/MemAccessUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -1811,9 +1811,11 @@ Result AccessUseDefChainVisitor<Impl, Result>::visit(SILValue sourceAddr) {
return asImpl().visitUnidentified(sourceAddr);

if (isGuaranteedAddressReturn(sourceAddr)) {
return asImpl().visitAccessProjection(
cast<ApplyInst>(sourceAddr),
&cast<ApplyInst>(sourceAddr)->getSelfArgumentOperand());
auto *selfOp = &cast<ApplyInst>(sourceAddr)->getSelfArgumentOperand();
if (selfOp->get()->getType().isObject()) {
return asImpl().visitUnidentified(sourceAddr);
}
return asImpl().visitAccessProjection(cast<ApplyInst>(sourceAddr), selfOp);
}

// Don't currently allow any other calls to return an accessed address.
Expand Down
2 changes: 2 additions & 0 deletions include/swift/SIL/SILValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,8 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {

bool isBeginApplyToken() const;

bool isBorrowAccessorResult() const;

/// Unsafely eliminate moveonly from this value's type. Returns true if the
/// value's underlying type was move only and thus was changed. Returns false
/// otherwise.
Expand Down
1 change: 1 addition & 0 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5062,6 +5062,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
TRIVIAL_ATTR_PRINTER(WeakLinked, weak_linked)
TRIVIAL_ATTR_PRINTER(Nonexhaustive, nonexhaustive)
TRIVIAL_ATTR_PRINTER(Concurrent, concurrent)
TRIVIAL_ATTR_PRINTER(UnsafeSelfDependentResult, unsafe_self_dependent_result)

#undef TRIVIAL_ATTR_PRINTER

Expand Down
3 changes: 2 additions & 1 deletion lib/ASTGen/Sources/ASTGen/DeclAttrs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,8 @@ extension ASTGenVisitor {
.UsableFromInline,
.Used,
.WarnUnqualifiedAccess,
.WeakLinked:
.WeakLinked,
.UnsafeSelfDependentResult:

return handle(self.generateSimpleDeclAttr(attribute: node, kind: attrKind!))

Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/CallEmission.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class CallEmission {
virtual void emitCallToUnmappedExplosion(llvm::CallBase *call,
Explosion &out) = 0;
void emitYieldsToExplosion(Explosion &out);
void emitGuaranteedAddressToExplosion(Explosion &out);
void setKeyPathAccessorArguments(Explosion &in, bool isOutlined,
Explosion &out);
virtual FunctionPointer getCalleeFunctionPointer() = 0;
Expand Down
36 changes: 36 additions & 0 deletions lib/IRGen/GenCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,10 @@ namespace {
/// function type.
void expandCoroutineContinuationType();

/// Initializes the result type for functions with @guaranteed_addr return
/// convention.
void expandGuaranteedAddressResult();

// Expand the components for the async continuation entrypoint of the
// function type (the function to be called on returning).
void expandAsyncReturnType();
Expand Down Expand Up @@ -694,6 +698,10 @@ void SignatureExpansion::expandResult(

auto fnConv = getSILFuncConventions();

if (fnConv.hasGuaranteedAddressResult()) {
return expandGuaranteedAddressResult();
}

// Disable the use of sret if we have multiple indirect results.
if (fnConv.getNumIndirectSILResults() > 1)
CanUseSRet = false;
Expand Down Expand Up @@ -911,6 +919,11 @@ void SignatureExpansion::expandCoroutineContinuationParameters() {
}
}

void SignatureExpansion::expandGuaranteedAddressResult() {
CanUseSRet = false;
ResultIRType = IGM.PtrTy;
}

void SignatureExpansion::addAsyncParameters() {
// using TaskContinuationFunction =
// SWIFT_CC(swift)
Expand Down Expand Up @@ -3933,6 +3946,11 @@ void CallEmission::emitYieldsToExplosion(Explosion &out) {
}
}

void CallEmission::emitGuaranteedAddressToExplosion(Explosion &out) {
auto call = emitCallSite();
out.add(call);
}

/// Emit the result of this call to an explosion.
void CallEmission::emitToExplosion(Explosion &out, bool isOutlined) {
assert(state == State::Emitting);
Expand All @@ -3948,6 +3966,14 @@ void CallEmission::emitToExplosion(Explosion &out, bool isOutlined) {

SILFunctionConventions fnConv(getCallee().getSubstFunctionType(),
IGF.getSILModule());

if (fnConv.hasGuaranteedAddressResult()) {
assert(LastArgWritten == 0 &&
"@guaranteed_addr along with indirect result?");
emitGuaranteedAddressToExplosion(out);
return;
}

SILType substResultType =
fnConv.getSILResultType(IGF.IGM.getMaximalTypeExpansionContext());

Expand Down Expand Up @@ -7001,6 +7027,16 @@ void irgen::emitYieldOnceCoroutineResult(IRGenFunction &IGF, Explosion &result,
}
}

void irgen::emitGuaranteedAddressResult(IRGenFunction &IGF, Explosion &result,
SILType funcResultType,
SILType returnResultType) {
assert(funcResultType == returnResultType);
assert(funcResultType.isAddress());
auto &Builder = IGF.Builder;
Builder.CreateRet(result.claimNext());
assert(result.empty());
}

FunctionPointer
IRGenFunction::getFunctionPointerForResumeIntrinsic(llvm::Value *resume) {
auto *fnTy = llvm::FunctionType::get(
Expand Down
4 changes: 4 additions & 0 deletions lib/IRGen/GenCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ namespace irgen {
void emitYieldOnceCoroutineResult(IRGenFunction &IGF, Explosion &result,
SILType funcResultType, SILType returnResultType);

void emitGuaranteedAddressResult(IRGenFunction &IGF, Explosion &result,
SILType funcResultType,
SILType returnResultType);

Address emitAutoDiffCreateLinearMapContextWithType(
IRGenFunction &IGF, llvm::Value *topLevelSubcontextMetatype);

Expand Down
21 changes: 20 additions & 1 deletion lib/IRGen/IRGenSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2032,6 +2032,11 @@ static ArrayRef<SILArgument *> emitEntryPointIndirectReturn(
SILFunctionConventions fnConv(funcTy, IGF.getSILModule());
SILType directResultType = IGF.CurSILFn->mapTypeIntoContext(
fnConv.getSILResultType(IGF.IGM.getMaximalTypeExpansionContext()));

if (fnConv.hasGuaranteedAddressResult()) {
return entry->getArguments();
}

if (requiresIndirectResult(directResultType)) {
auto &paramTI = IGF.IGM.getTypeInfo(directResultType);
auto &retTI =
Expand Down Expand Up @@ -3934,7 +3939,11 @@ void IRGenSILFunction::visitFullApplySite(FullApplySite site) {

// For a simple apply, just bind the apply result to the result of the call.
if (auto apply = dyn_cast<ApplyInst>(i)) {
setLoweredExplosion(apply, result);
if (apply->hasGuaranteedAddressResult()) {
setCorrespondingLoweredValues(apply->getResults(), result);
} else {
setLoweredExplosion(apply, result);
}
emission->end();

// For begin_apply, we have to destructure the call.
Expand Down Expand Up @@ -4451,6 +4460,16 @@ static void emitReturnInst(IRGenSILFunction &IGF,
return;
}

if (conv.hasGuaranteedAddressResult()) {
assert(IGF.CurSILFn->getLoweredFunctionType()->getLanguage() ==
SILFunctionLanguage::Swift);
auto funcResultType = IGF.CurSILFn->mapTypeIntoContext(
conv.getSILResultType(IGF.IGM.getMaximalTypeExpansionContext()));

emitGuaranteedAddressResult(IGF, result, funcResultType, resultTy);
return;
}

// The invariant on the out-parameter is that it's always zeroed, so
// there's nothing to do here.

Expand Down
24 changes: 9 additions & 15 deletions lib/SIL/IR/SILFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1387,18 +1387,15 @@ class DestructureResults {
TypeExpansionContext context;
bool hasSendingResult;
bool isBorrowOrMutateAccessor;
bool hasSelfWithAddressType;

public:
DestructureResults(TypeExpansionContext context, TypeConverter &TC,
const Conventions &conventions,
SmallVectorImpl<SILResultInfo> &results,
bool hasSendingResult, bool isBorrowOrMutateAccessor,
bool hasSelfWithAddressType)
bool hasSendingResult, bool isBorrowOrMutateAccessor)
: TC(TC), Convs(conventions), Results(results), context(context),
hasSendingResult(hasSendingResult),
isBorrowOrMutateAccessor(isBorrowOrMutateAccessor),
hasSelfWithAddressType(hasSelfWithAddressType) {}
isBorrowOrMutateAccessor(isBorrowOrMutateAccessor) {}

void destructure(AbstractionPattern origType, CanType substType) {
// Recur into tuples.
Expand Down Expand Up @@ -1452,9 +1449,10 @@ class DestructureResults {
ResultConvention convention;

if (isBorrowOrMutateAccessor) {
if ((hasSelfWithAddressType && !substResultTL.isTrivial()) ||
isFormallyReturnedIndirectly(origType, substType,
substResultTLForConvention)) {
if (substResultTL.isTrivial()) {
convention = ResultConvention::Unowned;
} else if (isFormallyReturnedIndirectly(origType, substType,
substResultTLForConvention)) {
assert(Convs.getResult(substResultTLForConvention) ==
ResultConvention::Guaranteed);
convention = ResultConvention::GuaranteedAddress;
Expand Down Expand Up @@ -2726,16 +2724,12 @@ static CanSILFunctionType getSILFunctionType(
coroutineOrigYieldType, coroutineSubstYieldType,
yields, coroutineKind);

bool hasSelfWithAddressType =
extInfoBuilder.hasSelfParam() &&
inputs.back().getSILStorageInterfaceType().isAddress();

// Destructure the result tuple type.
SmallVector<SILResultInfo, 8> results;
{
DestructureResults destructurer(
expansionContext, TC, conventions, results, hasSendingResult,
isBorrowOrMutateAccessor(constant), hasSelfWithAddressType);
DestructureResults destructurer(expansionContext, TC, conventions, results,
hasSendingResult,
isBorrowOrMutateAccessor(constant));
destructurer.destructure(origResultType, substFormalResultType);
}

Expand Down
13 changes: 8 additions & 5 deletions lib/SIL/IR/SILValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,7 @@ bool ValueBase::isGuaranteedForwarding() const {
return phi->isGuaranteedForwarding();
}

auto *applyInst = dyn_cast_or_null<ApplyInst>(getDefiningInstruction());
if (!applyInst) {
return false;
}
return applyInst->hasGuaranteedResult();
return isBorrowAccessorResult();
}

bool ValueBase::isBeginApplyToken() const {
Expand All @@ -210,6 +206,13 @@ bool ValueBase::isBeginApplyToken() const {
return result->isBeginApplyToken();
}

bool ValueBase::isBorrowAccessorResult() const {
auto *apply = dyn_cast_or_null<ApplyInst>(getDefiningInstruction());
if (!apply)
return false;
return apply->hasGuaranteedResult() || apply->hasGuaranteedAddressResult();
}

bool ValueBase::hasDebugTrace() const {
for (auto *op : getUses()) {
if (auto *debugValue = dyn_cast<DebugValueInst>(op->getUser())) {
Expand Down
16 changes: 16 additions & 0 deletions lib/SIL/Utils/InstructionUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,22 @@ SILValue swift::lookThroughOwnershipInsts(SILValue v) {
}
}

SILValue swift::lookThroughMoveOnlyCheckerPattern(SILValue value) {
auto *bbi = dyn_cast<BeginBorrowInst>(value);
if (!bbi) {
return value;
}
auto *muncvi = cast<MarkUnresolvedNonCopyableValueInst>(bbi->getOperand());
if (!muncvi) {
return value;
}
auto *cvi = cast<CopyValueInst>(muncvi->getOperand());
if (!cvi) {
return value;
}
return cvi->getOperand();
}

bool swift::visitNonOwnershipUses(SILValue value,
function_ref<bool(Operand *)> visitor) {
// All ownership insts have a single operand, so a recursive walk is
Expand Down
Loading