revert r27466 to unbreak the botz.

Swift SVN r27467
This commit is contained in:
Chris Lattner
2015-04-19 14:45:55 +00:00
parent 474a2ef084
commit 104d7e03ed

View File

@@ -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'.