mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
revert r27466 to unbreak the botz.
Swift SVN r27467
This commit is contained in:
@@ -181,20 +181,20 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
|
||||
(void)selfTy;
|
||||
assert(!selfTy.hasReferenceSemantics() && "can't emit a ref type ctor here");
|
||||
|
||||
// Allocate the local variable for 'self'.
|
||||
emitLocalVariableWithCleanup(selfDecl, false)->finishInitialization(*this);
|
||||
|
||||
// Emit a local variable for 'self'.
|
||||
// FIXME: The (potentially partially initialized) variable would need to be
|
||||
// cleaned up on an error unwind.
|
||||
emitLocalVariable(selfDecl,
|
||||
isDelegating ? MarkUninitializedInst::DelegatingSelf
|
||||
: MarkUninitializedInst::RootSelf);
|
||||
|
||||
// Mark self as being uninitialized so that DI knows where it is and how to
|
||||
// check for it.
|
||||
SILValue selfLV;
|
||||
SILValue selfLV, selfBox;
|
||||
{
|
||||
auto &SelfVarLoc = VarLocs[selfDecl];
|
||||
selfBox = SelfVarLoc.box;
|
||||
selfLV = SelfVarLoc.value;
|
||||
|
||||
auto MUIKind = isDelegating ? MarkUninitializedInst::DelegatingSelf
|
||||
: MarkUninitializedInst::RootSelf;
|
||||
selfLV = B.createMarkUninitialized(selfDecl, SelfVarLoc.value, MUIKind);
|
||||
SelfVarLoc.value = selfLV;
|
||||
}
|
||||
|
||||
// FIXME: Handle 'self' along with the other body patterns.
|
||||
@@ -207,16 +207,12 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
|
||||
|
||||
// Create a basic block to jump to for the implicit 'self' return.
|
||||
// We won't emit this until after we've emitted the body.
|
||||
// The epilog takes a the type of self as a return because the return of
|
||||
// 'self' is implicit.
|
||||
auto resultType = selfDecl->getType()->getInOutObjectType();
|
||||
if (ctor->getFailability() != OTK_None)
|
||||
resultType = OptionalType::get(ctor->getFailability(), resultType);
|
||||
prepareEpilog(resultType, ctor->isBodyThrowing(), CleanupLocation(ctor));
|
||||
// The epilog takes a void return because the return of 'self' is implicit.
|
||||
prepareEpilog(Type(), ctor->isBodyThrowing(), CleanupLocation(ctor));
|
||||
|
||||
// If the constructor can fail, set up an alternative epilog for constructor
|
||||
// failure.
|
||||
JumpDest failureExitDest = JumpDest::invalid();
|
||||
SILBasicBlock *failureExitBB = nullptr;
|
||||
SILArgument *failureExitArg = nullptr;
|
||||
auto &resultLowering = getTypeLowering(ctor->getResultType());
|
||||
|
||||
@@ -226,10 +222,7 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
|
||||
// On failure, we'll clean up everything (except self, which should have
|
||||
// been cleaned up before jumping here) and return nil instead.
|
||||
SavedInsertionPoint savedIP(*this, failureBB, FunctionSection::Postmatter);
|
||||
SILBasicBlock *failureExitBB = createBasicBlock();
|
||||
failureExitDest = JumpDest(failureExitBB, getCleanupsDepth(),
|
||||
CleanupLocation(ctor));
|
||||
|
||||
failureExitBB = createBasicBlock();
|
||||
Cleanups.emitCleanupsForReturn(ctor);
|
||||
// Return nil.
|
||||
if (lowering.isAddressOnly()) {
|
||||
@@ -268,64 +261,97 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
|
||||
// Emit the constructor body.
|
||||
emitStmt(ctor->getBody());
|
||||
|
||||
// If the end of the body is reachable, return self.
|
||||
if (B.hasValidInsertionPoint()) {
|
||||
auto cleanupLoc = CleanupLocation::get(ctor);
|
||||
|
||||
SILValue result;
|
||||
|
||||
// If 'self' is address-only, copy 'self' into the indirect return slot.
|
||||
if (lowering.isAddressOnly()) {
|
||||
assert(IndirectReturnAddress &&
|
||||
"no indirect return for address-only ctor?!");
|
||||
|
||||
// Get the address to which to store the result.
|
||||
SILValue returnAddress;
|
||||
switch (ctor->getFailability()) {
|
||||
case OTK_None:
|
||||
// For non-failable initializers, store to the return address directly.
|
||||
returnAddress = IndirectReturnAddress;
|
||||
break;
|
||||
// If this is a failable initializer, project out the payload.
|
||||
case OTK_Optional:
|
||||
case OTK_ImplicitlyUnwrappedOptional:
|
||||
returnAddress = B.createInitEnumDataAddr(ctor, IndirectReturnAddress,
|
||||
getASTContext().getOptionalSomeDecl(ctor->getFailability()),
|
||||
selfLV.getType());
|
||||
break;
|
||||
}
|
||||
|
||||
// We have to do a non-take copy because someone else may be using the box.
|
||||
B.createCopyAddr(cleanupLoc, selfLV, returnAddress,
|
||||
IsNotTake, IsInitialization);
|
||||
|
||||
// Inject the enum tag if the result is optional because of failability.
|
||||
if (ctor->getFailability() != OTK_None) {
|
||||
// Inject the 'Some' tag.
|
||||
B.createInjectEnumAddr(ctor, IndirectReturnAddress,
|
||||
getASTContext().getOptionalSomeDecl(ctor->getFailability()));
|
||||
}
|
||||
} else {
|
||||
// Otherwise, load and return the final 'self' value.
|
||||
result = B.createLoad(cleanupLoc, selfLV);
|
||||
|
||||
// Inject the self value into an optional if the constructor is failable.
|
||||
if (ctor->getFailability() != OTK_None) {
|
||||
result = B.createEnum(ctor, result,
|
||||
getASTContext().getOptionalSomeDecl(ctor->getFailability()),
|
||||
getLoweredLoadableType(ctor->getResultType()));
|
||||
}
|
||||
}
|
||||
|
||||
auto Dest = failureExitDest.isValid() ? failureExitDest : ReturnDest;
|
||||
Cleanups.emitBranchAndCleanups(Dest, ctor,
|
||||
result ? result : ArrayRef<SILValue>{});
|
||||
}
|
||||
|
||||
emitEpilog(ctor);
|
||||
Optional<SILValue> maybeReturnValue;
|
||||
SILLocation returnLoc(ctor);
|
||||
std::tie(maybeReturnValue, returnLoc) = emitEpilogBB(ctor);
|
||||
|
||||
// Don't finish without emitting the rethrow epilog.
|
||||
defer([&]{ emitRethrowEpilog(ctor); });
|
||||
|
||||
// Return 'self' in the epilog.
|
||||
if (!maybeReturnValue)
|
||||
return;
|
||||
|
||||
auto cleanupLoc = CleanupLocation::get(ctor);
|
||||
|
||||
assert(selfBox && "self should be a mutable box");
|
||||
|
||||
// If 'self' is address-only, copy 'self' into the indirect return slot.
|
||||
if (lowering.isAddressOnly()) {
|
||||
assert(IndirectReturnAddress &&
|
||||
"no indirect return for address-only ctor?!");
|
||||
|
||||
// Get the address to which to store the result.
|
||||
SILValue returnAddress;
|
||||
switch (ctor->getFailability()) {
|
||||
// For non-failable initializers, store to the return address directly.
|
||||
case OTK_None:
|
||||
returnAddress = IndirectReturnAddress;
|
||||
break;
|
||||
// If this is a failable initializer, project out the payload.
|
||||
case OTK_Optional:
|
||||
case OTK_ImplicitlyUnwrappedOptional:
|
||||
returnAddress = B.createInitEnumDataAddr(ctor, IndirectReturnAddress,
|
||||
getASTContext().getOptionalSomeDecl(ctor->getFailability()),
|
||||
selfLV.getType());
|
||||
break;
|
||||
}
|
||||
|
||||
// We have to do a non-take copy because someone else may be using the box.
|
||||
B.createCopyAddr(cleanupLoc, selfLV, returnAddress,
|
||||
IsNotTake, IsInitialization);
|
||||
B.emitStrongRelease(cleanupLoc, selfBox);
|
||||
|
||||
// Inject the enum tag if the result is optional because of failability.
|
||||
switch (ctor->getFailability()) {
|
||||
case OTK_None:
|
||||
// Not optional.
|
||||
break;
|
||||
|
||||
case OTK_Optional:
|
||||
case OTK_ImplicitlyUnwrappedOptional:
|
||||
// Inject the 'Some' tag.
|
||||
B.createInjectEnumAddr(ctor, IndirectReturnAddress,
|
||||
getASTContext().getOptionalSomeDecl(ctor->getFailability()));
|
||||
break;
|
||||
}
|
||||
|
||||
if (failureExitBB) {
|
||||
B.createBranch(returnLoc, failureExitBB);
|
||||
} else {
|
||||
B.createReturn(returnLoc, emitEmptyTuple(ctor));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, load and return the final 'self' value.
|
||||
SILValue selfValue = B.createLoad(cleanupLoc, selfLV);
|
||||
|
||||
// We have to do a retain because someone else may be using the box.
|
||||
lowering.emitRetainValue(B, cleanupLoc, selfValue);
|
||||
|
||||
// Release the box.
|
||||
B.emitStrongRelease(cleanupLoc, selfBox);
|
||||
|
||||
// Inject the self value into an optional if the constructor is failable.
|
||||
switch (ctor->getFailability()) {
|
||||
case OTK_None:
|
||||
// Not optional.
|
||||
break;
|
||||
|
||||
case OTK_Optional:
|
||||
case OTK_ImplicitlyUnwrappedOptional:
|
||||
selfValue = B.createEnum(ctor, selfValue,
|
||||
getASTContext().getOptionalSomeDecl(ctor->getFailability()),
|
||||
getLoweredLoadableType(ctor->getResultType()));
|
||||
break;
|
||||
}
|
||||
|
||||
if (failureExitBB) {
|
||||
B.createBranch(returnLoc, failureExitBB, selfValue);
|
||||
} else {
|
||||
B.createReturn(returnLoc, selfValue);
|
||||
}
|
||||
}
|
||||
|
||||
static void emitAddressOnlyEnumConstructor(SILGenFunction &gen,
|
||||
@@ -697,12 +723,20 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
|
||||
}
|
||||
|
||||
// Inject the self value into an optional if the constructor is failable.
|
||||
if (ctor->getFailability() != OTK_None) {
|
||||
switch (ctor->getFailability()) {
|
||||
case OTK_None:
|
||||
// Not optional.
|
||||
break;
|
||||
|
||||
case OTK_Optional:
|
||||
case OTK_ImplicitlyUnwrappedOptional: {
|
||||
RegularLocation loc(ctor);
|
||||
loc.markAutoGenerated();
|
||||
selfArg = B.createEnum(loc, selfArg,
|
||||
getASTContext().getOptionalSomeDecl(ctor->getFailability()),
|
||||
getLoweredLoadableType(ctor->getResultType()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the final 'self'.
|
||||
|
||||
Reference in New Issue
Block a user