Skip to content

Commit 4da795f

Browse files
authored
Merge pull request #80297 from rjmccall/zero-objc-async-result-on-error-path
Pass a zero normal result to ObjC async completion handlers on the error path
2 parents 98d6480 + e9ebc7c commit 4da795f

File tree

16 files changed

+147
-55
lines changed

16 files changed

+147
-55
lines changed

include/swift/AST/Builtins.def

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -719,9 +719,6 @@ BUILTIN_MISC_OPERATION(IsNegative, "isNegative", "n", Special)
719719
/// (_ value: Builtin.IntLiteral, _ index: Builtin.Word) -> Builtin.Word
720720
BUILTIN_MISC_OPERATION(WordAtIndex, "wordAtIndex", "n", Special)
721721

722-
/// zeroInitializer has type <T> () -> T
723-
BUILTIN_MISC_OPERATION(ZeroInitializer, "zeroInitializer", "n", Special)
724-
725722
/// once has type (Builtin.RawPointer, (Builtin.RawPointer) -> ())
726723
BUILTIN_MISC_OPERATION(Once, "once", "", Special)
727724
/// onceWithContext has type (Builtin.RawPointer, (Builtin.RawPointer) -> (), Builtin.RawPointer)
@@ -842,6 +839,10 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(Strideof, "strideof", "n", Special)
842839
/// Alignof has type T.Type -> Int
843840
BUILTIN_MISC_OPERATION_WITH_SILGEN(Alignof, "alignof", "n", Special)
844841

842+
/// zeroInitializer has type <T> () -> T, but the SIL builtin has its
843+
/// own rules.
844+
BUILTIN_MISC_OPERATION_WITH_SILGEN(ZeroInitializer, "zeroInitializer", "n", Special)
845+
845846
// getCurrentExecutor: () async -> Builtin.Executor?
846847
//
847848
// Retrieve the SerialExecutorRef on which the current asynchronous

include/swift/SIL/SILBuilder.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,6 +2422,16 @@ class SILBuilder {
24222422
valueType, paramType));
24232423
}
24242424

2425+
/// Create a zero-initialized value of the given (loadable) type.
2426+
///
2427+
/// This is currently only expected to be used in narrow situations
2428+
/// involving bridging and only makes a best effort attempt.
2429+
SILValue createZeroInitValue(SILLocation loc, SILType loweredTy);
2430+
2431+
/// Zero-initialize an object in memory of the given type (which may
2432+
/// or may not be loadable).
2433+
BuiltinInst *createZeroInitAddr(SILLocation loc, SILValue addr);
2434+
24252435
//===--------------------------------------------------------------------===//
24262436
// Unchecked cast helpers
24272437
//===--------------------------------------------------------------------===//

lib/IRGen/GenBuiltin.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,18 +1327,18 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
13271327
}
13281328

13291329
if (Builtin.ID == BuiltinValueKind::ZeroInitializer) {
1330-
// Build a zero initializer of the result type.
1331-
auto valueTy = getLoweredTypeAndTypeInfo(IGF.IGM,
1332-
substitutions.getReplacementTypes()[0]);
1333-
13341330
if (args.size() > 0) {
1331+
auto valueType = argTypes[0];
1332+
auto &valueTI = IGF.IGM.getTypeInfo(valueType);
1333+
13351334
// `memset` the memory addressed by the argument.
13361335
auto address = args.claimNext();
1337-
IGF.Builder.CreateMemSet(valueTy.second.getAddressForPointer(address),
1336+
IGF.Builder.CreateMemSet(valueTI.getAddressForPointer(address),
13381337
llvm::ConstantInt::get(IGF.IGM.Int8Ty, 0),
1339-
valueTy.second.getSize(IGF, argTypes[0]));
1338+
valueTI.getSize(IGF, valueType));
13401339
} else {
1341-
auto schema = valueTy.second.getSchema();
1340+
auto &resultTI = cast<LoadableTypeInfo>(IGF.IGM.getTypeInfo(resultType));
1341+
auto schema = resultTI.getSchema();
13421342
for (auto &elt : schema) {
13431343
out.add(llvm::Constant::getNullValue(elt.getScalarType()));
13441344
}

lib/IRGen/LoadableByAddress.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4165,9 +4165,9 @@ class AssignAddressToDef : SILInstructionVisitor<AssignAddressToDef> {
41654165
BuiltinValueKind::ZeroInitializer) {
41664166
auto build = assignment.getBuilder(++bi->getIterator());
41674167
auto newAddr = assignment.createAllocStack(bi->getType());
4168+
build.createZeroInitAddr(bi->getLoc(), newAddr);
41684169
assignment.mapValueToAddress(origValue, newAddr);
4169-
build.createStore(bi->getLoc(), origValue, newAddr,
4170-
StoreOwnershipQualifier::Unqualified);
4170+
assignment.markForDeletion(bi);
41714171
} else {
41724172
singleValueInstructionFallback(bi);
41734173
}

lib/SIL/IR/SILBuilder.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,26 @@ CheckedCastBranchInst *SILBuilder::createCheckedCastBranch(
805805
target2Count, forwardingOwnershipKind));
806806
}
807807

808+
BuiltinInst *SILBuilder::createZeroInitAddr(SILLocation loc, SILValue addr) {
809+
assert(addr->getType().isAddress());
810+
auto &C = getASTContext();
811+
auto zeroInit = getBuiltinValueDecl(C, C.getIdentifier("zeroInitializer"));
812+
return createBuiltin(loc, zeroInit->getBaseIdentifier(),
813+
SILType::getEmptyTupleType(C),
814+
SubstitutionMap(),
815+
addr);
816+
}
817+
818+
SILValue SILBuilder::createZeroInitValue(SILLocation loc, SILType loweredTy) {
819+
assert(loweredTy.isObject());
820+
auto &C = getASTContext();
821+
auto zeroInit = getBuiltinValueDecl(C, C.getIdentifier("zeroInitializer"));
822+
return createBuiltin(loc, zeroInit->getBaseIdentifier(),
823+
loweredTy,
824+
SubstitutionMap(),
825+
{});
826+
}
827+
808828
void SILBuilderWithScope::insertAfter(SILInstruction *inst,
809829
function_ref<void(SILBuilder &)> func) {
810830
if (isa<TermInst>(inst)) {

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
10091009
#define requireAddressType(type, value, valueDescription) \
10101010
_requireAddressType<type>(value, valueDescription, #type)
10111011

1012+
void requireVoidObjectType(SILType type, const Twine &valueDescription) {
1013+
_require(type.isObject() && type.isVoid(),
1014+
valueDescription + " must be a scalar of type ()");
1015+
}
1016+
10121017
template <class T>
10131018
typename CanTypeWrapperTraits<T>::type
10141019
_forbidObjectType(SILType type, const Twine &valueDescription,
@@ -2375,6 +2380,23 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
23752380
auto builtinKind = BI->getBuiltinKind();
23762381
auto arguments = BI->getArguments();
23772382

2383+
if (builtinKind == BuiltinValueKind::ZeroInitializer) {
2384+
require(!BI->getSubstitutions(),
2385+
"zeroInitializer has no generic arguments as a SIL builtin");
2386+
if (arguments.size() == 0) {
2387+
require(!fnConv.useLoweredAddresses()
2388+
|| BI->getType().isLoadable(*BI->getFunction()),
2389+
"scalar zeroInitializer must have a loadable result type");
2390+
} else {
2391+
require(arguments.size() == 1,
2392+
"zeroInitializer cannot have multiple arguments");
2393+
require(arguments[0]->getType().isAddress(),
2394+
"zeroInitializer argument must have address type");
2395+
requireVoidObjectType(BI->getType(),
2396+
"result of zeroInitializer");
2397+
}
2398+
}
2399+
23782400
// Check that 'getCurrentAsyncTask' only occurs within an async function.
23792401
if (builtinKind == BuiltinValueKind::GetCurrentAsyncTask) {
23802402
require(F.isAsync(),

lib/SILGen/SILGenBridging.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1985,8 +1985,9 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
19851985
auto param = completionTy->getParameters()[i];
19861986
auto paramTy = param.getSILStorageInterfaceType();
19871987
if (paramTy.isTrivial(F)) {
1988-
// If it's trivial, the value passed doesn't matter.
1989-
completionHandlerArgs.push_back(SILUndef::get(&F, paramTy));
1988+
// If it's trivial, pass a zero value of whatever the type is.
1989+
auto zero = B.createZeroInitValue(loc, paramTy);
1990+
completionHandlerArgs.push_back(zero);
19901991
} else {
19911992
// If it's not trivial, it must be a nullable class type. Pass
19921993
// nil.

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2097,6 +2097,26 @@ static ManagedValue emitBuiltinAddressOfRawLayout(SILGenFunction &SGF,
20972097
return ManagedValue::forObjectRValueWithoutOwnership(bi);
20982098
}
20992099

2100+
static ManagedValue emitBuiltinZeroInitializer(SILGenFunction &SGF,
2101+
SILLocation loc,
2102+
SubstitutionMap subs,
2103+
ArrayRef<ManagedValue> args,
2104+
SGFContext C) {
2105+
auto valueType = subs.getReplacementTypes()[0]->getCanonicalType();
2106+
auto &valueTL = SGF.getTypeLowering(valueType);
2107+
auto loweredValueTy = valueTL.getLoweredType().getObjectType();
2108+
2109+
if (valueTL.isLoadable() ||
2110+
!SGF.F.getConventions().useLoweredAddresses()) {
2111+
auto value = SGF.B.createZeroInitValue(loc, loweredValueTy);
2112+
return SGF.emitManagedRValueWithCleanup(value, valueTL);
2113+
}
2114+
2115+
SILValue valueAddr = SGF.getBufferForExprResult(loc, loweredValueTy, C);
2116+
SGF.B.createZeroInitAddr(loc, valueAddr);
2117+
return SGF.manageBufferForExprResult(valueAddr, valueTL, C);
2118+
}
2119+
21002120
static ManagedValue emitBuiltinEmplace(SILGenFunction &SGF,
21012121
SILLocation loc,
21022122
SubstitutionMap subs,
@@ -2129,15 +2149,7 @@ static ManagedValue emitBuiltinEmplace(SILGenFunction &SGF,
21292149
// Aside from providing a modicum of predictability if the memory isn't
21302150
// actually initialized, this also serves to communicate to DI that the memory
21312151
// is considered initialized from this point.
2132-
auto zeroInit = getBuiltinValueDecl(Ctx,
2133-
Ctx.getIdentifier("zeroInitializer"));
2134-
SGF.B.createBuiltin(loc, zeroInit->getBaseIdentifier(),
2135-
SILType::getEmptyTupleType(Ctx),
2136-
SubstitutionMap::get(zeroInit->getInnermostDeclContext()
2137-
->getGenericSignatureOfContext(),
2138-
{resultASTTy},
2139-
LookUpConformanceInModule()),
2140-
buffer);
2152+
SGF.B.createZeroInitAddr(loc, buffer);
21412153

21422154
SILValue bufferPtr = SGF.B.createAddressToPointer(loc, buffer,
21432155
SILType::getPrimitiveObjectType(SGF.getASTContext().TheRawPointerType),

lib/SILGen/SILGenConstructor.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -739,15 +739,7 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
739739
if (nominal->getAttrs().hasAttribute<RawLayoutAttr>()) {
740740
// Raw memory is not directly decomposable, but we still want to mark
741741
// it as initialized. Use a zero initializer.
742-
auto &C = ctor->getASTContext();
743-
auto zeroInit = getBuiltinValueDecl(C, C.getIdentifier("zeroInitializer"));
744-
B.createBuiltin(ctor, zeroInit->getBaseIdentifier(),
745-
SILType::getEmptyTupleType(C),
746-
SubstitutionMap::get(zeroInit->getInnermostDeclContext()
747-
->getGenericSignatureOfContext(),
748-
{selfDecl->getTypeInContext()},
749-
LookUpConformanceInModule()),
750-
selfLV.getLValueAddress());
742+
B.createZeroInitAddr(ctor, selfLV.getLValueAddress());
751743
} else if (isa<StructDecl>(nominal)
752744
&& lowering.getLoweredType().isMoveOnly()
753745
&& nominal->getStoredProperties().empty()) {

test/ClangImporter/objc_init_blocks.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// Make sure that the SIL ownership verifier passes.
88
// UnsafeUnretainedBlockClass.init()
99
// CHECK-LABEL: sil hidden @$s16objc_init_blocks26UnsafeUnretainedBlockClassCACycfc : $@convention(method) (@owned UnsafeUnretainedBlockClass) -> @owned UnsafeUnretainedBlockClass {
10-
// CHECK: [[ZI:%.*]] = builtin "zeroInitializer"<objc_bool_block>() : $objc_bool_block
10+
// CHECK: [[ZI:%.*]] = builtin "zeroInitializer"() : $objc_bool_block
1111
// CHECK: store [[ZI]] to %{{.*}} : $*objc_bool_block
1212
// CHECK-LABEL: } // end sil function '$s16objc_init_blocks26UnsafeUnretainedBlockClassCACycfc'
1313
open class UnsafeUnretainedBlockClass {

0 commit comments

Comments
 (0)