Skip to content

Commit e567bc9

Browse files
committed
[+0-all-args] Enable +0 normal arguments.
rdar://34222540
1 parent c1bc576 commit e567bc9

File tree

237 files changed

+3183
-3792
lines changed

Some content is hidden

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

237 files changed

+3183
-3792
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ option(SWIFT_STDLIB_ENABLE_SIL_OWNERSHIP
305305

306306
option(SWIFT_ENABLE_GUARANTEED_NORMAL_ARGUMENTS
307307
"Build the standard libraries, overlays, and runtime with normal arguments at +0"
308-
FALSE)
308+
TRUE)
309309

310310
option(SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS
311311
"Enable runtime function counters and expose the API."

include/swift/AST/SILOptions.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class SILOptions {
114114
llvm::StringRef ExternalPassPipelineFilename;
115115

116116
/// Emit normal function arguments using the +0 guaranteed convention.
117-
bool EnableGuaranteedNormalArguments = false;
117+
bool EnableGuaranteedNormalArguments = true;
118118

119119
/// Don't generate code using partial_apply in SIL generation.
120120
bool DisableSILPartialApply = false;

lib/SIL/SILOwnershipVerifier.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ llvm::cl::opt<bool> IsSILOwnershipVerifierTestingEnabled(
6262
"comment in SILOwnershipVerifier.cpp above option for more "
6363
"information."));
6464

65+
/// This is an option to turn off ownership verification on a specific file. We
66+
/// still emit code as if we are in ownership mode, but we do not verify. This
67+
/// is useful for temporarily turning off verification on tests.
68+
static llvm::cl::opt<bool>
69+
DisableOwnershipVerification("disable-sil-ownership-verification");
70+
6571
//===----------------------------------------------------------------------===//
6672
// Generalized User
6773
//===----------------------------------------------------------------------===//
@@ -2206,6 +2212,9 @@ bool SILValueOwnershipChecker::checkDataflow() {
22062212

22072213
void SILInstruction::verifyOperandOwnership() const {
22082214
#ifndef NDEBUG
2215+
if (DisableOwnershipVerification)
2216+
return;
2217+
22092218
if (isStaticInitializerInst())
22102219
return;
22112220

@@ -2251,6 +2260,9 @@ void SILInstruction::verifyOperandOwnership() const {
22512260

22522261
void SILValue::verifyOwnership(SILModule &Mod, DeadEndBlocks *DEBlocks) const {
22532262
#ifndef NDEBUG
2263+
if (DisableOwnershipVerification)
2264+
return;
2265+
22542266
// If we are SILUndef, just bail. SILUndef can pair with anything. Any uses of
22552267
// the SILUndef will make sure that the matching checks out.
22562268
if (isa<SILUndef>(*this))

lib/SILGen/SILGenApply.cpp

+3-7
Original file line numberDiff line numberDiff line change
@@ -1960,13 +1960,9 @@ class DelayedArgument {
19601960
// Recurse.
19611961
optValue = emitBindOptionals(SGF, optValue, bind->getSubExpr());
19621962

1963-
// Check whether the value is non-nil.
1964-
SGF.emitBindOptional(bind, optValue, bind->getDepth());
1965-
1966-
// Extract the non-optional value.
1967-
auto &optTL = SGF.getTypeLowering(optValue.getType());
1968-
auto value = SGF.emitUncheckedGetOptionalValueFrom(bind, optValue, optTL);
1969-
return value;
1963+
// Check whether the value is non-nil and if the value is not-nil, return
1964+
// the unwrapped value.
1965+
return SGF.emitBindOptional(bind, optValue, bind->getDepth());
19701966
}
19711967

19721968
std::pair<ManagedValue, ManagedValue>

lib/SILGen/SILGenBridging.cpp

+30-10
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,10 @@ static ManagedValue emitManagedParameter(SILGenFunction &SGF, SILLocation loc,
306306
return SGF.emitManagedRValueWithCleanup(value, valueTL);
307307

308308
case ParameterConvention::Direct_Guaranteed:
309+
// If we have a guaranteed parameter, the object should not need to be
310+
// retained or have a cleanup.
311+
return ManagedValue::forUnmanaged(value);
312+
309313
case ParameterConvention::Direct_Unowned:
310314
// We need to independently retain the value.
311315
return SGF.emitManagedRetain(loc, value, valueTL);
@@ -315,9 +319,9 @@ static ManagedValue emitManagedParameter(SILGenFunction &SGF, SILLocation loc,
315319

316320
case ParameterConvention::Indirect_In_Guaranteed:
317321
if (valueTL.isLoadable()) {
318-
return SGF.emitLoad(loc, value, valueTL, SGFContext(), IsNotTake);
322+
return SGF.B.createLoadBorrow(loc, ManagedValue::forUnmanaged(value));
319323
} else {
320-
return SGF.emitManagedRetain(loc, value, valueTL);
324+
return ManagedValue::forUnmanaged(value);
321325
}
322326

323327
case ParameterConvention::Indirect_In:
@@ -1118,12 +1122,20 @@ ManagedValue SILGenFunction::emitBridgedToNativeError(SILLocation loc,
11181122
assert(bridgeFnType->getResults()[0].getConvention()
11191123
== ResultConvention::Owned);
11201124
auto nativeErrorType = bridgeFnConv.getSILType(bridgeFnType->getResults()[0]);
1121-
assert(bridgeFnType->getParameters()[0].getConvention()
1122-
== ParameterConvention::Direct_Owned);
1125+
1126+
SILValue arg;
1127+
if (SGM.M.getOptions().EnableGuaranteedNormalArguments) {
1128+
assert(bridgeFnType->getParameters()[0].getConvention() ==
1129+
ParameterConvention::Direct_Guaranteed);
1130+
arg = bridgedError.getValue();
1131+
} else {
1132+
assert(bridgeFnType->getParameters()[0].getConvention() ==
1133+
ParameterConvention::Direct_Owned);
1134+
arg = bridgedError.forward(*this);
1135+
}
11231136

11241137
SILValue nativeError = B.createApply(loc, bridgeFn, bridgeFn->getType(),
1125-
nativeErrorType, {},
1126-
bridgedError.forward(*this));
1138+
nativeErrorType, {}, arg);
11271139
return emitManagedRValueWithCleanup(nativeError);
11281140
}
11291141

@@ -1166,12 +1178,20 @@ ManagedValue SILGenFunction::emitNativeToBridgedError(SILLocation loc,
11661178
== ResultConvention::Owned);
11671179
auto loweredBridgedErrorType =
11681180
bridgeFnConv.getSILType(bridgeFnType->getResults()[0]);
1169-
assert(bridgeFnType->getParameters()[0].getConvention()
1170-
== ParameterConvention::Direct_Owned);
1181+
1182+
SILValue arg;
1183+
if (SGM.M.getOptions().EnableGuaranteedNormalArguments) {
1184+
assert(bridgeFnType->getParameters()[0].getConvention() ==
1185+
ParameterConvention::Direct_Guaranteed);
1186+
arg = nativeError.getValue();
1187+
} else {
1188+
assert(bridgeFnType->getParameters()[0].getConvention() ==
1189+
ParameterConvention::Direct_Owned);
1190+
arg = nativeError.forward(*this);
1191+
}
11711192

11721193
SILValue bridgedError = B.createApply(loc, bridgeFn, bridgeFn->getType(),
1173-
loweredBridgedErrorType, {},
1174-
nativeError.forward(*this));
1194+
loweredBridgedErrorType, {}, arg);
11751195
return emitManagedRValueWithCleanup(bridgedError);
11761196
}
11771197

lib/SILGen/SILGenBuilder.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -901,3 +901,22 @@ ManagedValue SILGenBuilder::createUncheckedAddrCast(SILLocation loc, ManagedValu
901901
SILValue cast = createUncheckedAddrCast(loc, op.forward(SGF), resultTy);
902902
return cloner.clone(cast);
903903
}
904+
905+
ManagedValue SILGenBuilder::tryCreateUncheckedRefCast(SILLocation loc,
906+
ManagedValue original,
907+
SILType type) {
908+
CleanupCloner cloner(*this, original);
909+
SILValue result = tryCreateUncheckedRefCast(loc, original.getValue(), type);
910+
if (!result)
911+
return ManagedValue();
912+
original.forward(SGF);
913+
return cloner.clone(result);
914+
}
915+
916+
ManagedValue SILGenBuilder::createUncheckedTrivialBitCast(SILLocation loc,
917+
ManagedValue original,
918+
SILType type) {
919+
SILValue result =
920+
SGF.B.createUncheckedTrivialBitCast(loc, original.getValue(), type);
921+
return ManagedValue::forUnmanaged(result);
922+
}

lib/SILGen/SILGenBuilder.h

+9
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,15 @@ class SILGenBuilder : public SILBuilder {
306306
ManagedValue createUpcast(SILLocation loc, ManagedValue original,
307307
SILType type);
308308

309+
using SILBuilder::tryCreateUncheckedRefCast;
310+
ManagedValue tryCreateUncheckedRefCast(SILLocation loc, ManagedValue original,
311+
SILType type);
312+
313+
using SILBuilder::createUncheckedTrivialBitCast;
314+
ManagedValue createUncheckedTrivialBitCast(SILLocation loc,
315+
ManagedValue original,
316+
SILType type);
317+
309318
using SILBuilder::createUncheckedRefCast;
310319
ManagedValue createUncheckedRefCast(SILLocation loc, ManagedValue original,
311320
SILType type);

lib/SILGen/SILGenBuiltin.cpp

+17-13
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ static ManagedValue emitBuiltinUnpin(SILGenFunction &SGF,
141141

142142
if (requireIsOptionalNativeObject(SGF, loc, subs[0].getReplacement())) {
143143
// Unpinning takes responsibility for the +1 handle.
144-
SGF.B.createStrongUnpin(loc, args[0].forward(SGF), SGF.B.getDefaultAtomicity());
144+
SGF.B.createStrongUnpin(loc, args[0].ensurePlusOne(SGF, loc).forward(SGF),
145+
SGF.B.getDefaultAtomicity());
145146
}
146147

147148
return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
@@ -293,7 +294,7 @@ static ManagedValue emitBuiltinInit(SILGenFunction &SGF,
293294

294295
TemporaryInitialization init(addr, CleanupHandle::invalid());
295296
SGF.emitExprInto(args[0], &init);
296-
297+
297298
return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
298299
}
299300

@@ -544,14 +545,16 @@ emitBuiltinCastReference(SILGenFunction &SGF,
544545
auto &toTL = SGF.getTypeLowering(toTy);
545546
assert(!fromTL.isTrivial() && !toTL.isTrivial() && "expected ref type");
546547

547-
if (!fromTL.isAddress() || !toTL.isAddress()) {
548-
if (auto refCast = SGF.B.tryCreateUncheckedRefCast(loc, args[0].getValue(),
548+
// TODO: Fix this API.
549+
if (!fromTL.isAddress() || !toTL.isAddress()) {
550+
if (auto refCast = SGF.B.tryCreateUncheckedRefCast(loc, args[0],
549551
toTL.getLoweredType())) {
550552
// Create a reference cast, forwarding the cleanup.
551553
// The cast takes the source reference.
552-
return ManagedValue(refCast, args[0].getCleanup());
554+
return refCast;
553555
}
554556
}
557+
555558
// We are either casting between address-only types, or cannot promote to a
556559
// cast of reference values.
557560
//
@@ -563,7 +566,7 @@ emitBuiltinCastReference(SILGenFunction &SGF,
563566
// TODO: For now, we leave invalid casts in address form so that the runtime
564567
// will trap. We could emit a noreturn call here instead which would provide
565568
// more information to the optimizer.
566-
SILValue srcVal = args[0].forward(SGF);
569+
SILValue srcVal = args[0].ensurePlusOne(SGF, loc).forward(SGF);
567570
SILValue fromAddr;
568571
if (!fromTL.isAddress()) {
569572
// Move the loadable value into a "source temp". Since the source and
@@ -636,16 +639,17 @@ static ManagedValue emitBuiltinReinterpretCast(SILGenFunction &SGF,
636639
});
637640
}
638641
// Create the appropriate bitcast based on the source and dest types.
639-
auto &in = args[0];
640-
SILValue out = SGF.B.createUncheckedBitCast(loc, in.getValue(),
641-
toTL.getLoweredType());
642+
ManagedValue in = args[0];
643+
SILType resultTy = toTL.getLoweredType();
644+
if (resultTy.isTrivial(SGF.getModule()))
645+
return SGF.B.createUncheckedTrivialBitCast(loc, in, resultTy);
642646

643-
// If the cast reduces to unchecked_ref_cast, then the source and dest
644-
// have identical cleanup, so just forward the cleanup as an optimization.
645-
if (isa<UncheckedRefCastInst>(out))
646-
return ManagedValue(out, in.getCleanup());
647+
// If we can perform a ref cast, just return.
648+
if (auto refCast = SGF.B.tryCreateUncheckedRefCast(loc, in, resultTy))
649+
return refCast;
647650

648651
// Otherwise leave the original cleanup and retain the cast value.
652+
SILValue out = SGF.B.createUncheckedBitwiseCast(loc, in.getValue(), resultTy);
649653
return SGF.emitManagedRetain(loc, out, toTL);
650654
}
651655

lib/SILGen/SILGenConvert.cpp

+11-3
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ SILGenFunction::emitInjectOptional(SILLocation loc,
6666
TemporaryInitialization init(objectBuf, CleanupHandle::invalid());
6767
ManagedValue objectResult = generator(SGFContext(&init));
6868
if (!objectResult.isInContext()) {
69-
objectResult.forwardInto(*this, loc, objectBuf);
69+
objectResult.ensurePlusOne(*this, loc)
70+
.forwardInto(*this, loc, objectBuf);
7071
}
7172

7273
// Finalize the outer optional buffer.
@@ -190,15 +191,21 @@ SILGenFunction::emitPreconditionOptionalHasValue(SILLocation loc,
190191
bool hadCleanup = optional.hasCleanup();
191192
bool hadLValue = optional.isLValue();
192193

193-
auto noneDecl = getASTContext().getOptionalNoneDecl();
194194
auto someDecl = getASTContext().getOptionalSomeDecl();
195+
auto noneDecl = getASTContext().getOptionalNoneDecl();
196+
197+
// If we have an object, make sure the object is at +1. All switch_enum of
198+
// objects is done at +1.
195199
if (optional.getType().isAddress()) {
196200
// We forward in the creation routine for
197201
// unchecked_take_enum_data_addr. switch_enum_addr is a +0 operation.
198202
B.createSwitchEnumAddr(loc, optional.getValue(),
199203
/*defaultDest*/ nullptr,
200204
{{someDecl, contBB}, {noneDecl, failBB}});
201205
} else {
206+
optional = optional.ensurePlusOne(*this, loc);
207+
hadCleanup = true;
208+
hadLValue = false;
202209
B.createSwitchEnum(loc, optional.forward(*this),
203210
/*defaultDest*/ nullptr,
204211
{{someDecl, contBB}, {noneDecl, failBB}});
@@ -775,7 +782,8 @@ ManagedValue SILGenFunction::emitExistentialErasure(
775782
*this));
776783
ManagedValue mv = F(SGFContext(init.get()));
777784
if (!mv.isInContext()) {
778-
init->copyOrInitValueInto(*this, loc, mv, /*init*/ true);
785+
init->copyOrInitValueInto(*this, loc, mv.ensurePlusOne(*this, loc),
786+
/*init*/ true);
779787
init->finishInitialization(*this);
780788
}
781789
});

0 commit comments

Comments
 (0)