Skip to content

Commit 80af02d

Browse files
authored
Merge pull request #3491 from swiftwasm/main
[pull] swiftwasm from main
2 parents f39823f + 1da7173 commit 80af02d

File tree

123 files changed

+1602
-651
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+1602
-651
lines changed

include/swift/ABI/TaskStatus.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ class TaskGroupTaskStatusRecord : public TaskStatusRecord {
182182

183183
/// Attach the passed in `child` task to this group.
184184
void attachChild(AsyncTask *child) {
185-
assert(child->groupChildFragment());
186185
assert(child->hasGroupChildFragment());
187186
assert(child->groupChildFragment()->getGroup() == getGroup());
188187

@@ -211,6 +210,33 @@ class TaskGroupTaskStatusRecord : public TaskStatusRecord {
211210
cur->childFragment()->setNextChild(child);
212211
}
213212

213+
void detachChild(AsyncTask *child) {
214+
assert(child && "cannot remove a null child from group");
215+
if (FirstChild == child) {
216+
FirstChild = getNextChildTask(child);
217+
return;
218+
}
219+
220+
AsyncTask *prev = FirstChild;
221+
// Remove the child from the linked list, i.e.:
222+
// prev -> afterPrev -> afterChild
223+
// ==
224+
// child -> afterChild
225+
// Becomes:
226+
// prev --------------> afterChild
227+
while (prev) {
228+
auto afterPrev = getNextChildTask(prev);
229+
230+
if (afterPrev == child) {
231+
auto afterChild = getNextChildTask(child);
232+
prev->childFragment()->setNextChild(afterChild);
233+
return;
234+
}
235+
236+
prev = afterPrev;
237+
}
238+
}
239+
214240
static AsyncTask *getNextChildTask(AsyncTask *task) {
215241
return task->childFragment()->getNextChild();
216242
}

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1496,7 +1496,7 @@ ERROR(access_control_extension_more,none,
14961496
"be declared %select{%error|fileprivate|internal|public|%error}2",
14971497
(AccessLevel, DescriptiveDeclKind, AccessLevel))
14981498
ERROR(access_control_extension_open,none,
1499-
"extensions cannot use 'open' as their default access; use 'public'",
1499+
"extensions cannot be declared 'open'; declare individual members as 'open' instead",
15001500
())
15011501
ERROR(access_control_open_bad_decl,none,
15021502
"only classes and overridable class members can be declared 'open';"

include/swift/SIL/SILBuilder.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,6 +2221,11 @@ class SILBuilder {
22212221
BranchInst *createBranch(SILLocation Loc, SILBasicBlock *TargetBlock,
22222222
OperandValueArrayRef Args);
22232223

2224+
// This only creates the terminator, not the results. Create the results with
2225+
// OwnershipForwardingTermInst::createResult() and
2226+
// SwitchEnumInst::createDefaultResult() to ensure that the result ownership
2227+
// is correct (it must be consistent with the switch_enum's forwarding
2228+
// ownership, which may differ from \p Operand's ownership).
22242229
SwitchValueInst *
22252230
createSwitchValue(SILLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
22262231
ArrayRef<std::pair<SILValue, SILBasicBlock *>> CaseBBs) {
@@ -2232,16 +2237,14 @@ class SILBuilder {
22322237
SILLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
22332238
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
22342239
Optional<ArrayRef<ProfileCounter>> CaseCounts = None,
2235-
ProfileCounter DefaultCount = ProfileCounter()) {
2236-
return createSwitchEnum(Loc, Operand, DefaultBB, CaseBBs, CaseCounts,
2237-
DefaultCount, Operand.getOwnershipKind());
2238-
}
2240+
ProfileCounter DefaultCount = ProfileCounter());
22392241

22402242
SwitchEnumInst *createSwitchEnum(
22412243
SILLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
22422244
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
22432245
Optional<ArrayRef<ProfileCounter>> CaseCounts,
2244-
ProfileCounter DefaultCount, ValueOwnershipKind forwardingOwnershipKind) {
2246+
ProfileCounter DefaultCount,
2247+
ValueOwnershipKind forwardingOwnershipKind) {
22452248
return insertTerminator(SwitchEnumInst::create(
22462249
getSILDebugLocation(Loc), Operand, DefaultBB, CaseBBs, getFunction(),
22472250
CaseCounts, DefaultCount, forwardingOwnershipKind));

include/swift/SIL/SILInstruction.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,7 @@ class OwnershipForwardingMixin {
10561056
ValueOwnershipKind ownershipKind)
10571057
: ownershipKind(ownershipKind) {
10581058
assert(isa(kind) && "Invalid subclass?!");
1059+
assert(ownershipKind && "invalid forwarding ownership");
10591060
}
10601061

10611062
public:
@@ -7877,6 +7878,7 @@ class TermInst : public NonValueInstruction {
78777878
}
78787879
};
78797880

7881+
// Forwards the first operand to a result in each successor block.
78807882
class OwnershipForwardingTermInst : public TermInst,
78817883
public OwnershipForwardingMixin {
78827884
protected:
@@ -7903,6 +7905,11 @@ class OwnershipForwardingTermInst : public TermInst,
79037905
return kind == SILInstructionKind::SwitchEnumInst ||
79047906
kind == SILInstructionKind::CheckedCastBranchInst;
79057907
}
7908+
7909+
SILValue getOperand() const { return getAllOperands()[0].get(); }
7910+
7911+
/// Create a result for this terminator on the given successor block.
7912+
SILPhiArgument *createResult(SILBasicBlock *succ, SILType resultTy);
79067913
};
79077914

79087915
/// UnreachableInst - Position in the code which would be undefined to reach.
@@ -8642,6 +8649,14 @@ class SwitchEnumInst
86428649
SILFunction &F, Optional<ArrayRef<ProfileCounter>> CaseCounts,
86438650
ProfileCounter DefaultCount,
86448651
ValueOwnershipKind forwardingOwnershipKind);
8652+
8653+
public:
8654+
/// Create the default result for a partially built switch_enum.
8655+
/// Returns nullptr if no default argument is needed.
8656+
SILPhiArgument *createDefaultResult();
8657+
8658+
/// Create the .some result for an optional switch_enum.
8659+
SILPhiArgument *createOptionalSomeResult();
86458660
};
86468661
/// A switch on an enum's discriminator in memory.
86478662
class SwitchEnumAddrInst

include/swift/SIL/SILInstructionWorklist.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,10 @@ class SILInstructionWorklist : SILInstructionWorklistBase {
185185
/// Intended to be called during visitation after \p instruction has been
186186
/// removed from the worklist.
187187
///
188-
/// \p instruction the instruction whose usages will be replaced
188+
/// \p instruction the instruction whose usages will be replaced. This
189+
/// instruction may already be deleted to maintain valid SIL. For example, if
190+
/// it was a block terminator.
191+
///
189192
/// \p result the instruction whose usages will replace \p instruction
190193
///
191194
/// \return whether the instruction was deleted or modified.

include/swift/Sema/CSFix.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,10 @@ enum class FixKind : uint8_t {
331331

332332
/// Specify a type for an explicitly written placeholder that could not be
333333
/// resolved.
334-
SpecifyTypeForPlaceholder
334+
SpecifyTypeForPlaceholder,
335+
336+
/// Allow `weak` declarations to be bound to a non-optional type.
337+
AllowNonOptionalWeak,
335338
};
336339

337340
class ConstraintFix {
@@ -2424,6 +2427,21 @@ class AllowInvalidStaticMemberRefOnProtocolMetatype final
24242427
create(ConstraintSystem &cs, ConstraintLocator *locator);
24252428
};
24262429

2430+
class AllowNonOptionalWeak final : public ConstraintFix {
2431+
AllowNonOptionalWeak(ConstraintSystem &cs, ConstraintLocator *locator)
2432+
: ConstraintFix(cs, FixKind::AllowNonOptionalWeak, locator) {}
2433+
2434+
public:
2435+
std::string getName() const override {
2436+
return "allow `weak` with non-optional type";
2437+
}
2438+
2439+
bool diagnose(const Solution &solution, bool asNote = false) const override;
2440+
2441+
static AllowNonOptionalWeak *create(ConstraintSystem &cs,
2442+
ConstraintLocator *locator);
2443+
};
2444+
24272445
} // end namespace constraints
24282446
} // end namespace swift
24292447

lib/Basic/Cache.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#if defined(__APPLE__)
14-
#include "Darwin/Cache-Mac.cpp"
14+
#include "Darwin/Cache-Mac.inc"
1515
#else
1616

1717
// This file implements a default caching implementation that never evicts
File renamed without changes.

lib/ClangImporter/ImportName.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,6 +1721,7 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
17211721
case clang::OverloadedOperatorKind::OO_Star:
17221722
case clang::OverloadedOperatorKind::OO_Slash:
17231723
case clang::OverloadedOperatorKind::OO_Percent:
1724+
case clang::OverloadedOperatorKind::OO_Caret:
17241725
case clang::OverloadedOperatorKind::OO_Amp:
17251726
case clang::OverloadedOperatorKind::OO_Pipe:
17261727
case clang::OverloadedOperatorKind::OO_Less:

lib/SIL/IR/SILBuilder.cpp

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -601,13 +601,74 @@ void SILBuilder::emitScopedBorrowOperation(SILLocation loc, SILValue original,
601601
createEndBorrow(loc, value);
602602
}
603603

604+
/// Attempt to propagate ownership from \p operand to the returned forwarding
605+
/// ownership where the forwarded value has type \p targetType. If this fails,
606+
/// return Owned forwarding ownership instead.
607+
///
608+
/// Propagation only fails when \p operand is dynamically trivial, as indicated
609+
/// by ownership None, AND \p targetType is statically nontrivial.
610+
///
611+
/// Example:
612+
///
613+
/// %e = enum $Optional<AnyObject>, #Optional.none!enumelt
614+
/// switch_enum %e : $Optional<AnyObject>,
615+
/// case #Optional.some!enumelt: bb2...,
616+
/// forwarding: @owned
617+
/// bb2(%arg : @owned AnyObject):
618+
///
619+
/// Example:
620+
///
621+
/// %mt = metatype $@thick C.Type
622+
/// checked_cast_br %mt : $@thick C.Type to AnyObject.Type, bb1, bb2,
623+
/// forwarding: @owned
624+
/// bb1(%arg : @owned AnyObject.Type):
625+
///
626+
/// If the forwarded value is statically known nontrivial, then the forwarding
627+
/// ownership cannot be None. Such a result is unreachable, but the SIL on that
628+
/// path must still be valid. When creating ownership out of thin air, default
629+
/// to Owned because that allows the value to be consumed without generating a
630+
/// copy. This does require the client code to handle ending the lifetime of an
631+
/// owned result even if the input was passed as guaranteed.
632+
///
633+
/// Note: For simplicitly, ownership None is not propagated for any statically
634+
/// nontrivial result, even if \p targetType may also be dynamically
635+
/// trivial. For example, the operand of a switch_enum could be a nested enum
636+
/// such that all switch cases may be dynamically trivial. Or a checked_cast_br
637+
/// could cast from one dynamically trivial enum to another. Figuring out
638+
/// whether the dynamically trivial operand value maps onto a dynamically
639+
/// trivial terminator result would be very complex with no practical benefit.
640+
static ValueOwnershipKind deriveForwardingOwnership(SILValue operand,
641+
SILType targetType,
642+
SILFunction &func) {
643+
if (operand.getOwnershipKind() != OwnershipKind::None
644+
|| targetType.isTrivial(func)) {
645+
return operand.getOwnershipKind();
646+
}
647+
return OwnershipKind::Owned;
648+
}
649+
650+
SwitchEnumInst *SILBuilder::createSwitchEnum(
651+
SILLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
652+
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
653+
Optional<ArrayRef<ProfileCounter>> CaseCounts,
654+
ProfileCounter DefaultCount) {
655+
// Consider the operand's type to be the target's type since a switch
656+
// covers all cases including the default argument.
657+
auto forwardingOwnership =
658+
deriveForwardingOwnership(Operand, Operand->getType(), getFunction());
659+
return createSwitchEnum(Loc, Operand, DefaultBB, CaseBBs, CaseCounts,
660+
DefaultCount, forwardingOwnership);
661+
}
662+
604663
CheckedCastBranchInst *SILBuilder::createCheckedCastBranch(
605664
SILLocation Loc, bool isExact, SILValue op,
606665
SILType destLoweredTy, CanType destFormalTy,
607666
SILBasicBlock *successBB, SILBasicBlock *failureBB,
608667
ProfileCounter target1Count, ProfileCounter target2Count) {
668+
auto forwardingOwnership =
669+
deriveForwardingOwnership(op, destLoweredTy, getFunction());
609670
return createCheckedCastBranch(Loc, isExact, op, destLoweredTy, destFormalTy,
610-
successBB, failureBB, op.getOwnershipKind(),
671+
successBB, failureBB, forwardingOwnership,
611672
target1Count, target2Count);
612673
}
613674

@@ -619,10 +680,11 @@ CheckedCastBranchInst *SILBuilder::createCheckedCastBranch(
619680
assert((!hasOwnership() || !failureBB->getNumArguments() ||
620681
failureBB->getArgument(0)->getType() == op->getType()) &&
621682
"failureBB's argument doesn't match incoming argument type");
683+
622684
return insertTerminator(CheckedCastBranchInst::create(
623685
getSILDebugLocation(Loc), isExact, op, destLoweredTy, destFormalTy,
624-
successBB, failureBB, getFunction(), target1Count,
625-
target2Count, forwardingOwnershipKind));
686+
successBB, failureBB, getFunction(), target1Count, target2Count,
687+
forwardingOwnershipKind));
626688
}
627689

628690
void SILBuilderWithScope::insertAfter(SILInstruction *inst,

lib/SIL/IR/SILInstructions.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2895,3 +2895,68 @@ ReturnInst::ReturnInst(SILFunction &func, SILDebugLocation debugLoc,
28952895
"Conflicting ownership kinds when creating term inst from function "
28962896
"result info?!");
28972897
}
2898+
2899+
// This may be called in an invalid SIL state. SILCombine creates new
2900+
// terminators in non-terminator position and defers deleting the original
2901+
// terminator until after all modification.
2902+
SILPhiArgument *OwnershipForwardingTermInst::createResult(SILBasicBlock *succ,
2903+
SILType resultTy) {
2904+
// The forwarding instruction declares a forwarding ownership kind that
2905+
// determines the ownership of its results.
2906+
auto resultOwnership = getForwardingOwnershipKind();
2907+
2908+
// Trivial results have no ownership. Although it is valid for a trivially
2909+
// typed value to have ownership, it is never necessary and less efficient.
2910+
if (resultTy.isTrivial(*getFunction())) {
2911+
resultOwnership = OwnershipKind::None;
2912+
2913+
} else if (resultOwnership == OwnershipKind::None) {
2914+
// switch_enum strangely allows results to acquire ownership out of thin
2915+
// air whenever the operand has no ownership and result is nontrivial:
2916+
// %e = enum $Optional<AnyObject>, #Optional.none!enumelt
2917+
// switch_enum %e : $Optional<AnyObject>,
2918+
// case #Optional.some!enumelt: bb2...
2919+
// bb2(%arg : @guaranteed T):
2920+
//
2921+
// We can either use None or Guaranteed. None would correctly propagate
2922+
// ownership and would maintain the invariant that guaranteed values are
2923+
// always within a borrow scope. However it would result in a nontrivial
2924+
// type without ownership. The lifetime verifier does not like that.
2925+
resultOwnership = OwnershipKind::Guaranteed;
2926+
}
2927+
return succ->createPhiArgument(resultTy, resultOwnership);
2928+
}
2929+
2930+
SILPhiArgument *SwitchEnumInst::createDefaultResult() {
2931+
auto *f = getFunction();
2932+
if (!f->hasOwnership())
2933+
return nullptr;
2934+
2935+
if (!hasDefault())
2936+
return nullptr;
2937+
2938+
assert(getDefaultBB()->getNumArguments() == 0 && "precondition");
2939+
2940+
auto enumTy = getOperand()->getType();
2941+
NullablePtr<EnumElementDecl> uniqueCase = getUniqueCaseForDefault();
2942+
2943+
// Without a unique default case, the OSSA result simply forwards the
2944+
// switch_enum operand.
2945+
if (!uniqueCase)
2946+
return createResult(getDefaultBB(), enumTy);
2947+
2948+
// With a unique default case, the result is materialized exactly the same way
2949+
// as a matched result. It has a value iff the unique case has a payload.
2950+
if (!uniqueCase.get()->hasAssociatedValues())
2951+
return nullptr;
2952+
2953+
auto resultTy = enumTy.getEnumElementType(uniqueCase.get(), f->getModule(),
2954+
f->getTypeExpansionContext());
2955+
return createResult(getDefaultBB(), resultTy);
2956+
}
2957+
2958+
SILPhiArgument *SwitchEnumInst::createOptionalSomeResult() {
2959+
auto someDecl = getModule().getASTContext().getOptionalSomeDecl();
2960+
auto someBB = getCaseDestination(someDecl);
2961+
return createResult(someBB, getOperand()->getType().unwrapOptionalType());
2962+
}

0 commit comments

Comments
 (0)