Skip to content

Commit c0cda72

Browse files
authored
Merge pull request #1863 from swiftwasm/main
[pull] swiftwasm from main
2 parents b6ae56b + 163d47e commit c0cda72

File tree

16 files changed

+205
-130
lines changed

16 files changed

+205
-130
lines changed

include/swift/SIL/SILCloner.h

+7
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,13 @@ template <typename ImplClass>
15421542
void SILCloner<ImplClass>::visitUncheckedValueCastInst(
15431543
UncheckedValueCastInst *Inst) {
15441544
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1545+
if (!getBuilder().hasOwnership()) {
1546+
recordClonedInstruction(Inst, getBuilder().createUncheckedBitwiseCast(
1547+
getOpLocation(Inst->getLoc()),
1548+
getOpValue(Inst->getOperand()),
1549+
getOpType(Inst->getType())));
1550+
return;
1551+
}
15451552
recordClonedInstruction(Inst, getBuilder().createUncheckedValueCast(
15461553
getOpLocation(Inst->getLoc()),
15471554
getOpValue(Inst->getOperand()),

include/swift/SIL/SILModule.h

+22
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,15 @@ class SILModule {
263263
/// to ensure that the module is serialized only once.
264264
bool serialized;
265265

266+
/// Set if we have registered a deserialization notification handler for
267+
/// lowering ownership in non transparent functions.
268+
/// This gets set in NonTransparent OwnershipModelEliminator pass.
269+
bool regDeserializationNotificationHandlerForNonTransparentFuncOME;
270+
/// Set if we have registered a deserialization notification handler for
271+
/// lowering ownership in transparent functions.
272+
/// This gets set in OwnershipModelEliminator pass.
273+
bool regDeserializationNotificationHandlerForAllFuncOME;
274+
266275
/// Action to be executed for serializing the SILModule.
267276
ActionCallback SerializeSILAction;
268277

@@ -301,6 +310,19 @@ class SILModule {
301310
deserializationNotificationHandlers.erase(handler);
302311
}
303312

313+
bool hasRegisteredDeserializationNotificationHandlerForNonTransparentFuncOME() {
314+
return regDeserializationNotificationHandlerForNonTransparentFuncOME;
315+
}
316+
bool hasRegisteredDeserializationNotificationHandlerForAllFuncOME() {
317+
return regDeserializationNotificationHandlerForAllFuncOME;
318+
}
319+
void setRegisteredDeserializationNotificationHandlerForNonTransparentFuncOME() {
320+
regDeserializationNotificationHandlerForNonTransparentFuncOME = true;
321+
}
322+
void setRegisteredDeserializationNotificationHandlerForAllFuncOME() {
323+
regDeserializationNotificationHandlerForAllFuncOME = true;
324+
}
325+
304326
/// Add a delete notification handler \p Handler to the module context.
305327
void registerDeleteNotificationHandler(DeleteNotificationHandler* Handler);
306328

include/swift/SILOptimizer/PassManager/PassManager.h

+5
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,11 @@ class SILPassManager {
281281
/// Run the passes in Transform from \p FromTransIdx to \p ToTransIdx.
282282
void runFunctionPasses(unsigned FromTransIdx, unsigned ToTransIdx);
283283

284+
/// Helper function to check if the function pass should be run mandatorily
285+
/// All passes in mandatory pass pipeline and ownership model elimination are
286+
/// mandatory function passes.
287+
bool isMandatoryFunctionPass(SILFunctionTransform *);
288+
284289
/// A helper function that returns (based on SIL stage and debug
285290
/// options) whether we should continue running passes.
286291
bool continueTransforming();

lib/SIL/IR/SILModule.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ class SILModule::SerializationCallback final
9595
SILModule::SILModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
9696
Lowering::TypeConverter &TC, const SILOptions &Options)
9797
: Stage(SILStage::Raw), Options(Options), serialized(false),
98+
regDeserializationNotificationHandlerForNonTransparentFuncOME(false),
99+
regDeserializationNotificationHandlerForAllFuncOME(false),
98100
SerializeSILAction(), Types(TC) {
99101
assert(!context.isNull());
100102
if (auto *file = context.dyn_cast<FileUnit *>()) {

lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp

+46-42
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ static void prepareSILFunctionForOptimization(ModuleDecl *, SILFunction *F) {
370370

371371
namespace {
372372

373-
struct OwnershipModelEliminator : SILModuleTransform {
373+
struct OwnershipModelEliminator : SILFunctionTransform {
374374
bool SkipTransparent;
375375
bool SkipStdlibModule;
376376

@@ -379,53 +379,50 @@ struct OwnershipModelEliminator : SILModuleTransform {
379379

380380
void run() override {
381381
if (DumpBefore.size()) {
382-
getModule()->dump(DumpBefore.c_str());
382+
getFunction()->dump(DumpBefore.c_str());
383383
}
384384

385-
auto &Mod = *getModule();
385+
auto *F = getFunction();
386+
auto &Mod = getFunction()->getModule();
386387

387388
// If we are supposed to skip the stdlib module and we are in the stdlib
388389
// module bail.
389390
if (SkipStdlibModule && Mod.isStdlibModule()) {
390391
return;
391392
}
392393

393-
for (auto &F : Mod) {
394-
// If F does not have ownership, skip it. We have no further work to do.
395-
if (!F.hasOwnership())
396-
continue;
397-
398-
// If we were asked to not strip ownership from transparent functions in
399-
// /our/ module, continue.
400-
if (SkipTransparent && F.isTransparent())
401-
continue;
402-
403-
// Verify here to make sure ownership is correct before we strip.
404-
{
405-
// Add a pretty stack trace entry to tell users who see a verification
406-
// failure triggered by this verification check that they need to re-run
407-
// with -sil-verify-all to actually find the pass that introduced the
408-
// verification error.
409-
//
410-
// DISCUSSION: This occurs due to the crash from the verification
411-
// failure happening in the pass itself. This causes us to dump the
412-
// SILFunction and emit a msg that this pass (OME) is the culprit. This
413-
// is generally correct for most passes, but not for OME since we are
414-
// verifying before we have even modified the function to ensure that
415-
// all ownership invariants have been respected before we lower
416-
// ownership from the function.
417-
llvm::PrettyStackTraceString silVerifyAllMsgOnFailure(
418-
"Found verification error when verifying before lowering "
419-
"ownership. Please re-run with -sil-verify-all to identify the "
420-
"actual pass that introduced the verification error.");
421-
F.verify();
422-
}
394+
if (!F->hasOwnership())
395+
return;
423396

424-
if (stripOwnership(F)) {
425-
auto InvalidKind =
426-
SILAnalysis::InvalidationKind::BranchesAndInstructions;
427-
invalidateAnalysis(&F, InvalidKind);
428-
}
397+
// If we were asked to not strip ownership from transparent functions in
398+
// /our/ module, return.
399+
if (SkipTransparent && F->isTransparent())
400+
return;
401+
402+
// Verify here to make sure ownership is correct before we strip.
403+
{
404+
// Add a pretty stack trace entry to tell users who see a verification
405+
// failure triggered by this verification check that they need to re-run
406+
// with -sil-verify-all to actually find the pass that introduced the
407+
// verification error.
408+
//
409+
// DISCUSSION: This occurs due to the crash from the verification
410+
// failure happening in the pass itself. This causes us to dump the
411+
// SILFunction and emit a msg that this pass (OME) is the culprit. This
412+
// is generally correct for most passes, but not for OME since we are
413+
// verifying before we have even modified the function to ensure that
414+
// all ownership invariants have been respected before we lower
415+
// ownership from the function.
416+
llvm::PrettyStackTraceString silVerifyAllMsgOnFailure(
417+
"Found verification error when verifying before lowering "
418+
"ownership. Please re-run with -sil-verify-all to identify the "
419+
"actual pass that introduced the verification error.");
420+
F->verify();
421+
}
422+
423+
if (stripOwnership(*F)) {
424+
auto InvalidKind = SILAnalysis::InvalidationKind::BranchesAndInstructions;
425+
invalidateAnalysis(InvalidKind);
429426
}
430427

431428
// If we were asked to strip transparent, we are at the beginning of the
@@ -435,12 +432,19 @@ struct OwnershipModelEliminator : SILModuleTransform {
435432
FunctionBodyDeserializationNotificationHandler;
436433
std::unique_ptr<DeserializationNotificationHandler> ptr;
437434
if (SkipTransparent) {
438-
ptr.reset(new NotificationHandlerTy(
439-
prepareNonTransparentSILFunctionForOptimization));
435+
if (!Mod.hasRegisteredDeserializationNotificationHandlerForNonTransparentFuncOME()) {
436+
ptr.reset(new NotificationHandlerTy(
437+
prepareNonTransparentSILFunctionForOptimization));
438+
Mod.registerDeserializationNotificationHandler(std::move(ptr));
439+
Mod.setRegisteredDeserializationNotificationHandlerForNonTransparentFuncOME();
440+
}
440441
} else {
441-
ptr.reset(new NotificationHandlerTy(prepareSILFunctionForOptimization));
442+
if (!Mod.hasRegisteredDeserializationNotificationHandlerForAllFuncOME()) {
443+
ptr.reset(new NotificationHandlerTy(prepareSILFunctionForOptimization));
444+
Mod.registerDeserializationNotificationHandler(std::move(ptr));
445+
Mod.setRegisteredDeserializationNotificationHandlerForAllFuncOME();
446+
}
442447
}
443-
Mod.registerDeserializationNotificationHandler(std::move(ptr));
444448
}
445449
};
446450

lib/SILOptimizer/PassManager/PassManager.cpp

+17-3
Original file line numberDiff line numberDiff line change
@@ -383,21 +383,35 @@ void SILPassManager::dumpPassInfo(const char *Title, unsigned TransIdx,
383383
llvm::dbgs() << '\n';
384384
}
385385

386+
bool SILPassManager::isMandatoryFunctionPass(SILFunctionTransform *sft) {
387+
return isMandatory || sft->getPassKind() ==
388+
PassKind::NonTransparentFunctionOwnershipModelEliminator ||
389+
sft->getPassKind() == PassKind::OwnershipModelEliminator ||
390+
sft->getPassKind() ==
391+
PassKind::NonStdlibNonTransparentFunctionOwnershipModelEliminator;
392+
}
393+
386394
void SILPassManager::runPassOnFunction(unsigned TransIdx, SILFunction *F) {
387395

388396
assert(analysesUnlocked() && "Expected all analyses to be unlocked!");
389397

390398
auto *SFT = cast<SILFunctionTransform>(Transformations[TransIdx]);
399+
400+
if (!F->shouldOptimize() && !isMandatoryFunctionPass(SFT)) {
401+
return;
402+
}
403+
391404
SFT->injectPassManager(this);
392405
SFT->injectFunction(F);
393406

394407
PrettyStackTraceSILFunctionTransform X(SFT, NumPassesRun);
395408
DebugPrintEnabler DebugPrint(NumPassesRun);
396409

397410
// If nothing changed since the last run of this pass, we can skip this
398-
// pass.
411+
// pass if it is not mandatory
399412
CompletedPasses &completedPasses = CompletedPassesMap[F];
400-
if (completedPasses.test((size_t)SFT->getPassKind()) &&
413+
if (!isMandatoryFunctionPass(SFT) &&
414+
completedPasses.test((size_t)SFT->getPassKind()) &&
401415
!SILDisableSkippingPasses) {
402416
if (SILPrintPassName)
403417
dumpPassInfo("(Skip)", TransIdx, F);
@@ -513,7 +527,7 @@ runFunctionPasses(unsigned FromTransIdx, unsigned ToTransIdx) {
513527

514528
// Only include functions that are definitions, and which have not
515529
// been intentionally excluded from optimization.
516-
if (F.isDefinition() && (isMandatory || F.shouldOptimize()))
530+
if (F.isDefinition())
517531
FunctionWorklist.push_back(*I);
518532
}
519533

lib/SILOptimizer/PassManager/PassPipeline.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,10 @@ void addFunctionPasses(SILPassPipelinePlan &P,
283283
// splits up copy_addr.
284284
P.addCopyForwarding();
285285

286+
// We earlier eliminated ownership if we are not compiling the stdlib. Now
287+
// handle the stdlib functions.
288+
P.addNonTransparentFunctionOwnershipModelEliminator();
289+
286290
// Optimize copies from a temporary (an "l-value") to a destination.
287291
P.addTempLValueOpt();
288292

@@ -489,10 +493,7 @@ static void addHighLevelFunctionPipeline(SILPassPipelinePlan &P) {
489493
// FIXME: update EagerSpecializer to be a function pass!
490494
P.addEagerSpecializer();
491495

492-
// We earlier eliminated ownership if we are not compiling the stdlib. Now
493-
// handle the stdlib functions.
494-
P.addNonTransparentFunctionOwnershipModelEliminator();
495-
496+
// stdlib ownership model elimination is done within addFunctionPasses
496497
addFunctionPasses(P, OptimizationLevelKind::HighLevel);
497498

498499
addHighLevelLoopOptPasses(P);

lib/Sema/CSBindings.cpp

+73-48
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,77 @@ bool TypeVarBindingProducer::computeNext() {
12171217
return true;
12181218
}
12191219

1220+
Optional<std::pair<ConstraintFix *, unsigned>>
1221+
TypeVariableBinding::fixForHole(ConstraintSystem &cs) const {
1222+
auto *dstLocator = TypeVar->getImpl().getLocator();
1223+
auto *srcLocator = Binding.getLocator();
1224+
1225+
unsigned defaultImpact = 1;
1226+
1227+
if (auto *GP = TypeVar->getImpl().getGenericParameter()) {
1228+
// If it is represetative for a key path root, let's emit a more
1229+
// specific diagnostic.
1230+
auto *keyPathRoot =
1231+
cs.isRepresentativeFor(TypeVar, ConstraintLocator::KeyPathRoot);
1232+
if (keyPathRoot) {
1233+
ConstraintFix *fix = SpecifyKeyPathRootType::create(
1234+
cs, keyPathRoot->getImpl().getLocator());
1235+
return std::make_pair(fix, defaultImpact);
1236+
} else {
1237+
auto path = dstLocator->getPath();
1238+
// Drop `generic parameter` locator element so that all missing
1239+
// generic parameters related to the same path can be coalesced later.
1240+
ConstraintFix *fix = DefaultGenericArgument::create(
1241+
cs, GP,
1242+
cs.getConstraintLocator(dstLocator->getAnchor(), path.drop_back()));
1243+
return std::make_pair(fix, defaultImpact);
1244+
}
1245+
}
1246+
1247+
if (TypeVar->getImpl().isClosureParameterType()) {
1248+
ConstraintFix *fix = SpecifyClosureParameterType::create(cs, dstLocator);
1249+
return std::make_pair(fix, defaultImpact);
1250+
}
1251+
1252+
if (TypeVar->getImpl().isClosureResultType()) {
1253+
auto *closure = castToExpr<ClosureExpr>(dstLocator->getAnchor());
1254+
// If the whole body is being ignored due to a pre-check failure,
1255+
// let's not record a fix about result type since there is
1256+
// just not enough context to infer it without a body.
1257+
if (cs.hasFixFor(cs.getConstraintLocator(closure->getBody()),
1258+
FixKind::IgnoreInvalidFunctionBuilderBody))
1259+
return None;
1260+
1261+
ConstraintFix *fix = SpecifyClosureReturnType::create(cs, dstLocator);
1262+
return std::make_pair(fix, defaultImpact);
1263+
}
1264+
1265+
if (srcLocator->directlyAt<ObjectLiteralExpr>()) {
1266+
ConstraintFix *fix = SpecifyObjectLiteralTypeImport::create(cs, dstLocator);
1267+
return std::make_pair(fix, defaultImpact);
1268+
}
1269+
1270+
if (srcLocator->isKeyPathRoot()) {
1271+
// If we recorded an invalid key path fix, let's skip this specify root
1272+
// type fix because it wouldn't produce a useful diagnostic.
1273+
auto *kpLocator = cs.getConstraintLocator(srcLocator->getAnchor());
1274+
if (cs.hasFixFor(kpLocator, FixKind::AllowKeyPathWithoutComponents))
1275+
return None;
1276+
1277+
ConstraintFix *fix = SpecifyKeyPathRootType::create(cs, dstLocator);
1278+
return std::make_pair(fix, defaultImpact);
1279+
}
1280+
1281+
if (dstLocator->directlyAt<NilLiteralExpr>()) {
1282+
// This is a dramatic event, it means that there is absolutely
1283+
// no contextual information to resolve type of `nil`.
1284+
ConstraintFix *fix = SpecifyContextualTypeForNil::create(cs, dstLocator);
1285+
return std::make_pair(fix, /*impact=*/(unsigned)10);
1286+
}
1287+
1288+
return None;
1289+
}
1290+
12201291
bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
12211292
auto type = Binding.BindingType;
12221293
auto *srcLocator = Binding.getLocator();
@@ -1238,56 +1309,10 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
12381309
// resolved and had to be bound to a placeholder "hole" type.
12391310
cs.increaseScore(SK_Hole);
12401311

1241-
ConstraintFix *fix = nullptr;
1242-
unsigned fixImpact = 1;
1243-
1244-
if (auto *GP = TypeVar->getImpl().getGenericParameter()) {
1245-
// If it is represetative for a key path root, let's emit a more
1246-
// specific diagnostic.
1247-
auto *keyPathRoot =
1248-
cs.isRepresentativeFor(TypeVar, ConstraintLocator::KeyPathRoot);
1249-
if (keyPathRoot) {
1250-
fix = SpecifyKeyPathRootType::create(
1251-
cs, keyPathRoot->getImpl().getLocator());
1252-
} else {
1253-
auto path = dstLocator->getPath();
1254-
// Drop `generic parameter` locator element so that all missing
1255-
// generic parameters related to the same path can be coalesced later.
1256-
fix = DefaultGenericArgument::create(
1257-
cs, GP,
1258-
cs.getConstraintLocator(dstLocator->getAnchor(),
1259-
path.drop_back()));
1260-
}
1261-
} else if (TypeVar->getImpl().isClosureParameterType()) {
1262-
fix = SpecifyClosureParameterType::create(cs, dstLocator);
1263-
} else if (TypeVar->getImpl().isClosureResultType()) {
1264-
auto *locator = TypeVar->getImpl().getLocator();
1265-
auto *closure = castToExpr<ClosureExpr>(locator->getAnchor());
1266-
// If the whole body is being ignored due to a pre-check failure,
1267-
// let's not record a fix about result type since there is
1268-
// just not enough context to infer it without a body.
1269-
if (!cs.hasFixFor(cs.getConstraintLocator(closure->getBody()),
1270-
FixKind::IgnoreInvalidFunctionBuilderBody))
1271-
fix = SpecifyClosureReturnType::create(cs, dstLocator);
1272-
} else if (srcLocator->directlyAt<ObjectLiteralExpr>()) {
1273-
fix = SpecifyObjectLiteralTypeImport::create(cs, dstLocator);
1274-
} else if (srcLocator->isKeyPathRoot()) {
1275-
// If we recorded an invalid key path fix, let's skip this specify root
1276-
// type fix because it wouldn't produce a useful diagnostic.
1277-
auto *kpLocator = cs.getConstraintLocator(srcLocator->getAnchor());
1278-
if (cs.hasFixFor(kpLocator, FixKind::AllowKeyPathWithoutComponents))
1312+
if (auto fix = fixForHole(cs)) {
1313+
if (cs.recordFix(/*fix=*/fix->first, /*impact=*/fix->second))
12791314
return true;
1280-
1281-
fix = SpecifyKeyPathRootType::create(cs, dstLocator);
1282-
} else if (dstLocator->directlyAt<NilLiteralExpr>()) {
1283-
fix = SpecifyContextualTypeForNil::create(cs, dstLocator);
1284-
// This is a dramatic event, it means that there is absolutely
1285-
// no contextual information to resolve type of `nil`.
1286-
fixImpact = 10;
12871315
}
1288-
1289-
if (fix && cs.recordFix(fix, fixImpact))
1290-
return true;
12911316
}
12921317
}
12931318

0 commit comments

Comments
 (0)