Skip to content

Commit dad20d8

Browse files
Merge pull request #5261 from swiftwasm/main
[pull] swiftwasm from main
2 parents 3054c47 + a81b0b6 commit dad20d8

23 files changed

+1088
-538
lines changed

.github/ISSUE_TEMPLATE/feature_request.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name: Feature request
33
about: Share an idea
44
title: ''
5-
labels: feature request, triage needed
5+
labels: feature, triage needed
66
assignees: ''
77

88
---

include/swift/AST/DiagnosticsSIL.def

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ ERROR(sil_moveonlychecker_owned_value_consumed_more_than_once, none,
730730
ERROR(sil_moveonlychecker_owned_value_consumed_and_used_at_same_time, none,
731731
"'%0' consumed and used at the same time", (StringRef))
732732
ERROR(sil_moveonlychecker_value_used_after_consume, none,
733-
"'%0' used after consume. Lifetime extension of variable requires a copy", (StringRef))
733+
"'%0' used after consume", (StringRef))
734734
ERROR(sil_moveonlychecker_guaranteed_value_consumed, none,
735735
"'%0' has guaranteed ownership but was consumed", (StringRef))
736736
ERROR(sil_moveonlychecker_guaranteed_value_captured_by_closure, none,
@@ -754,6 +754,8 @@ NOTE(sil_moveonlychecker_boundary_use, none,
754754
"boundary use here", ())
755755
NOTE(sil_moveonlychecker_consuming_use_here, none,
756756
"consuming use here", ())
757+
NOTE(sil_moveonlychecker_other_consuming_use_here, none,
758+
"other consuming use here", ())
757759
NOTE(sil_moveonlychecker_two_consuming_uses_here, none,
758760
"two consuming uses here", ())
759761
NOTE(sil_moveonlychecker_consuming_and_non_consuming_uses_here, none,
@@ -762,6 +764,9 @@ NOTE(sil_moveonlychecker_consuming_closure_use_here, none,
762764
"closure capture here", ())
763765
NOTE(sil_moveonlychecker_nonconsuming_use_here, none,
764766
"non-consuming use here", ())
767+
NOTE(sil_movekillscopyablevalue_value_cyclic_consumed_in_loop_here, none,
768+
"consuming in loop use here", ())
769+
765770
ERROR(sil_moveonlychecker_not_understand_no_implicit_copy, none,
766771
"Usage of @noImplicitCopy that the move checker does not know how to "
767772
"check!", ())

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6679,6 +6679,8 @@ ERROR(noimplicitcopy_attr_invalid_in_generic_context,
66796679
ERROR(moveonly_generics, none, "move-only type %0 cannot be used with generics yet", (Type))
66806680
ERROR(noimplicitcopy_attr_not_allowed_on_moveonlytype,none,
66816681
"'@_noImplicitCopy' has no effect when applied to a move only type", ())
6682+
ERROR(moveonly_enums_do_not_support_indirect,none,
6683+
"move-only enum %0 cannot be marked indirect or have indirect cases yet", (Identifier))
66826684

66836685
//------------------------------------------------------------------------------
66846686
// MARK: Type inference from default expressions

include/swift/SIL/PrunedLiveness.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,10 @@
132132
#include "swift/SIL/OwnershipUtils.h"
133133
#include "swift/SIL/SILBasicBlock.h"
134134
#include "swift/SIL/SILFunction.h"
135+
#include "swift/SIL/SILInstruction.h"
135136
#include "llvm/ADT/MapVector.h"
136137
#include "llvm/ADT/PointerIntPair.h"
138+
#include "llvm/ADT/STLExtras.h"
137139
#include "llvm/ADT/SmallVector.h"
138140

139141
namespace swift {
@@ -542,6 +544,76 @@ class PrunedLiveness {
542544
return useIter->second ? LifetimeEndingUse : NonLifetimeEndingUse;
543545
}
544546

547+
using ConstUserRange =
548+
iterator_range<const std::pair<SILInstruction *, bool> *>;
549+
ConstUserRange getAllUsers() const {
550+
return llvm::make_range(users.begin(), users.end());
551+
}
552+
553+
/// A namespace containing helper functors for use with various mapped
554+
/// ranges. Intended to be used to hide these noise types when working in an
555+
/// IDE.
556+
struct RangeIterationHelpers {
557+
struct MapFunctor {
558+
SILInstruction *
559+
operator()(const std::pair<SILInstruction *, bool> &pair) const {
560+
// Strip off the const to ease use with other APIs.
561+
return const_cast<SILInstruction *>(pair.first);
562+
}
563+
};
564+
565+
struct LifetimeEnding {
566+
struct FilterFunctor {
567+
bool operator()(const std::pair<SILInstruction *, bool> &pair) const {
568+
return pair.second;
569+
}
570+
};
571+
572+
using MapFilterIter = llvm::mapped_iterator<
573+
llvm::filter_iterator<const std::pair<SILInstruction *, bool> *,
574+
FilterFunctor>,
575+
MapFunctor>;
576+
};
577+
578+
struct NonLifetimeEnding {
579+
struct FilterFunctor {
580+
bool operator()(const std::pair<SILInstruction *, bool> &pair) const {
581+
return !pair.second;
582+
}
583+
};
584+
585+
using MapFilterIter = llvm::mapped_iterator<
586+
llvm::filter_iterator<const std::pair<SILInstruction *, bool> *,
587+
FilterFunctor>,
588+
MapFunctor>;
589+
};
590+
};
591+
using LifetimeEndingUserRange = llvm::iterator_range<
592+
RangeIterationHelpers::LifetimeEnding::MapFilterIter>;
593+
594+
/// Return a range consisting of the current set of consuming users fed into
595+
/// this PrunedLiveness instance.
596+
LifetimeEndingUserRange getLifetimeEndingUsers() const {
597+
return map_range(
598+
llvm::make_filter_range(
599+
getAllUsers(),
600+
RangeIterationHelpers::LifetimeEnding::FilterFunctor()),
601+
RangeIterationHelpers::MapFunctor());
602+
}
603+
604+
using NonLifetimeEndingUserRange = llvm::iterator_range<
605+
RangeIterationHelpers::NonLifetimeEnding::MapFilterIter>;
606+
607+
/// Return a range consisting of the current set of non lifetime ending users
608+
/// fed into this PrunedLiveness instance.
609+
NonLifetimeEndingUserRange getNonLifetimeEndingUsers() const {
610+
return map_range(
611+
llvm::make_filter_range(
612+
getAllUsers(),
613+
RangeIterationHelpers::NonLifetimeEnding::FilterFunctor()),
614+
RangeIterationHelpers::MapFunctor());
615+
}
616+
545617
void print(llvm::raw_ostream &OS) const;
546618
void dump() const;
547619
};

include/swift/SILOptimizer/Utils/CanonicalizeOSSALifetime.h

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -213,15 +213,6 @@ class CanonicalizeOSSALifetime final {
213213
/// copies.
214214
bool maximizeLifetime;
215215

216-
/// If true and we are processing a value of move_only type, emit a diagnostic
217-
/// when-ever we need to insert a copy_value.
218-
std::function<void(Operand *)> moveOnlyCopyValueNotification;
219-
220-
/// If true and we are processing a value of move_only type, pass back to the
221-
/// caller any consuming uses that are going to be used as part of the final
222-
/// lifetime boundary in case we need to emit diagnostics.
223-
std::function<void(Operand *)> moveOnlyFinalConsumingUse;
224-
225216
// If present, will be used to ensure that the lifetime is not shortened to
226217
// end inside an access scope which it previously enclosed. (Note that ending
227218
// before such an access scope is fine regardless.)
@@ -289,27 +280,10 @@ class CanonicalizeOSSALifetime final {
289280
}
290281
}
291282

292-
void maybeNotifyMoveOnlyCopy(Operand *use) {
293-
if (!moveOnlyCopyValueNotification)
294-
return;
295-
moveOnlyCopyValueNotification(use);
296-
}
297-
298-
void maybeNotifyFinalConsumingUse(Operand *use) {
299-
if (!moveOnlyFinalConsumingUse)
300-
return;
301-
moveOnlyFinalConsumingUse(use);
302-
}
303-
304-
CanonicalizeOSSALifetime(
305-
bool pruneDebugMode, bool maximizeLifetime,
306-
NonLocalAccessBlockAnalysis *accessBlockAnalysis, DominanceInfo *domTree,
307-
InstructionDeleter &deleter,
308-
std::function<void(Operand *)> moveOnlyCopyValueNotification = nullptr,
309-
std::function<void(Operand *)> moveOnlyFinalConsumingUse = nullptr)
283+
CanonicalizeOSSALifetime(bool pruneDebugMode, bool maximizeLifetime,
284+
NonLocalAccessBlockAnalysis *accessBlockAnalysis,
285+
DominanceInfo *domTree, InstructionDeleter &deleter)
310286
: pruneDebugMode(pruneDebugMode), maximizeLifetime(maximizeLifetime),
311-
moveOnlyCopyValueNotification(moveOnlyCopyValueNotification),
312-
moveOnlyFinalConsumingUse(moveOnlyFinalConsumingUse),
313287
accessBlockAnalysis(accessBlockAnalysis), domTree(domTree),
314288
deleter(deleter),
315289
liveness(maximizeLifetime ? &discoveredBlocks : nullptr) {}
@@ -348,8 +322,52 @@ class CanonicalizeOSSALifetime final {
348322
/// operands.
349323
bool canonicalizeValueLifetime(SILValue def);
350324

325+
/// Compute the liveness information for \p def. But do not do any rewriting
326+
/// or computation of boundaries.
327+
///
328+
/// The intention is that this is used if one wants to emit diagnostics using
329+
/// the liveness information before doing any rewriting.
330+
bool computeLiveness(SILValue def);
331+
332+
/// Given the already computed liveness boundary for the given def, rewrite
333+
/// copies of def as appropriate.
334+
///
335+
/// NOTE: It is assumed that one passes the extended boundary from \see
336+
/// computeLiveness.
337+
///
338+
/// NOTE: It is assumed that one has emitted any diagnostics.
339+
void rewriteLifetimes();
340+
341+
/// Return the pure original boundary just based off of liveness information
342+
/// without maximizing or extending liveness.
343+
void findOriginalBoundary(PrunedLivenessBoundary &resultingOriginalBoundary);
344+
351345
InstModCallbacks &getCallbacks() { return deleter.getCallbacks(); }
352346

347+
using IsInterestingUser = PrunedLiveness::IsInterestingUser;
348+
349+
/// Helper method that returns the isInterestingUser status of \p user in the
350+
/// passed in Liveness.
351+
///
352+
/// NOTE: Only call this after calling computeLivenessBoundary or the results
353+
/// will not be initialized.
354+
IsInterestingUser isInterestingUser(SILInstruction *user) const {
355+
return liveness.isInterestingUser(user);
356+
}
357+
358+
using LifetimeEndingUserRange = PrunedLiveness::LifetimeEndingUserRange;
359+
LifetimeEndingUserRange getLifetimeEndingUsers() const {
360+
return liveness.getLifetimeEndingUsers();
361+
}
362+
363+
using NonLifetimeEndingUserRange = PrunedLiveness::NonLifetimeEndingUserRange;
364+
NonLifetimeEndingUserRange getNonLifetimeEndingUsers() const {
365+
return liveness.getNonLifetimeEndingUsers();
366+
}
367+
368+
using UserRange = PrunedLiveness::ConstUserRange;
369+
UserRange getUsers() const { return liveness.getAllUsers(); }
370+
353371
private:
354372
void recordDebugValue(DebugValueInst *dvi) { debugValues.insert(dvi); }
355373

@@ -362,8 +380,6 @@ class CanonicalizeOSSALifetime final {
362380

363381
void extendLivenessThroughOverlappingAccess();
364382

365-
void findOriginalBoundary(PrunedLivenessBoundary &boundary);
366-
367383
void findExtendedBoundary(PrunedLivenessBoundary const &originalBoundary,
368384
PrunedLivenessBoundary &boundary);
369385

lib/SILOptimizer/Mandatory/MoveOnlyAddressChecker.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,8 @@ bool GatherUsesVisitor::visitUse(Operand *op, AccessUseType useTy) {
10121012
// For convenience, grab the user of op.
10131013
auto *user = op->getUser();
10141014

1015+
LLVM_DEBUG(llvm::dbgs() << "Visiting user: " << *user);
1016+
10151017
// First check if we have init/reinit. These are quick/simple.
10161018
if (::memInstMustInitialize(op)) {
10171019
LLVM_DEBUG(llvm::dbgs() << "Found init: " << *user);

lib/SILOptimizer/Mandatory/MoveOnlyBorrowToDestructureTransform.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -294,11 +294,11 @@ void BorrowToDestructureTransform::checkForErrorsOnSameInstruction() {
294294
continue;
295295

296296
if (badOperand->isConsuming())
297-
diagnosticEmitter.emitObjectConsumesDestructuredValueTwice(
298-
mmci, use, badOperand);
297+
diagnosticEmitter.emitObjectInstConsumesValueTwice(mmci, use,
298+
badOperand);
299299
else
300-
diagnosticEmitter.emitObjectConsumesAndUsesDestructuredValue(
301-
mmci, use, badOperand);
300+
diagnosticEmitter.emitObjectInstConsumesAndUsesValue(mmci, use,
301+
badOperand);
302302
emittedError = true;
303303
}
304304

@@ -359,7 +359,9 @@ bool BorrowToDestructureTransform::gatherBorrows(
359359
return true;
360360
}
361361

362-
LLVM_DEBUG(llvm::dbgs() << "Searching for borrows for inst: " << *mmci);
362+
LLVM_DEBUG(llvm::dbgs() << "Performing BorrowToDestructureTramsform!\n"
363+
"Searching for borrows for inst: "
364+
<< *mmci);
363365

364366
StackList<Operand *> worklist(mmci->getFunction());
365367
for (auto *op : mmci->getUses())

0 commit comments

Comments
 (0)