3232using namespace swift ;
3333using namespace irgen ;
3434
35- void OutliningMetadataCollector::collectTypeMetadataForLayout (SILType type ) {
35+ void OutliningMetadataCollector::collectTypeMetadataForLayout (SILType ty ) {
3636 // If the type has no archetypes, we can emit it from scratch in the callee.
37- if (!type .hasArchetype ()) {
37+ if (!ty .hasArchetype ()) {
3838 return ;
3939 }
4040
4141 // Substitute opaque types if allowed.
42- type =
43- IGF.IGM .substOpaqueTypesWithUnderlyingTypes (type, CanGenericSignature ());
42+ ty = IGF.IGM .substOpaqueTypesWithUnderlyingTypes (ty, CanGenericSignature ());
4443
45- auto formalType = type.getASTType ();
46- auto &ti = IGF.IGM .getTypeInfoForLowered (formalType);
44+ auto astType = ty.getASTType ();
45+ auto &ti = IGF.IGM .getTypeInfoForLowered (astType);
46+
47+ if (needsDeinit) {
48+ auto *nominal = ty.getASTType ()->getAnyNominal ();
49+ if (nominal && nominal->getValueTypeDestructor ()) {
50+ assert (ty.isMoveOnly ());
51+ collectFormalTypeMetadata (ty.getASTType ());
52+ }
53+ }
54+
55+ if (!needsLayout) {
56+ return ;
57+ }
4758
4859 // We don't need the metadata for fixed size types or types that are not ABI
4960 // accessible. Outlining will call the value witness of the enclosing type of
@@ -55,16 +66,11 @@ void OutliningMetadataCollector::collectTypeMetadataForLayout(SILType type) {
5566 // If the type is a legal formal type, add it as a formal type.
5667 // FIXME: does this force us to emit a more expensive metadata than we need
5768 // to?
58- if (formalType ->isLegalFormalType ()) {
59- return collectFormalTypeMetadata (formalType );
69+ if (astType ->isLegalFormalType ()) {
70+ return collectFormalTypeMetadata (astType );
6071 }
6172
62- auto key = LocalTypeDataKey (type.getASTType (),
63- LocalTypeDataKind::forRepresentationTypeMetadata ());
64- if (Values.count (key)) return ;
65-
66- auto metadata = IGF.emitTypeMetadataRefForLayout (type);
67- Values.insert ({key, metadata});
73+ collectRepresentationTypeMetadata (ty);
6874}
6975
7076void OutliningMetadataCollector::collectFormalTypeMetadata (CanType type) {
@@ -78,6 +84,15 @@ void OutliningMetadataCollector::collectFormalTypeMetadata(CanType type) {
7884 Values.insert ({key, metadata});
7985}
8086
87+ void OutliningMetadataCollector::collectRepresentationTypeMetadata (SILType ty) {
88+ auto key = LocalTypeDataKey (
89+ ty.getASTType (), LocalTypeDataKind::forRepresentationTypeMetadata ());
90+ if (Values.count (key))
91+ return ;
92+
93+ auto metadata = IGF.emitTypeMetadataRefForLayout (ty);
94+ Values.insert ({key, metadata});
95+ }
8196
8297void OutliningMetadataCollector::addMetadataArguments (
8398 SmallVectorImpl<llvm::Value*> &args) const {
@@ -136,11 +151,12 @@ irgen::getTypeAndGenericSignatureForManglingOutlineFunction(SILType type) {
136151}
137152
138153bool TypeInfo::withMetadataCollector (
139- IRGenFunction &IGF, SILType T,
154+ IRGenFunction &IGF, SILType T, LayoutIsNeeded_t needsLayout,
155+ DeinitIsNeeded_t needsDeinit,
140156 llvm::function_ref<void (OutliningMetadataCollector &)> invocation) const {
141157 if (!T.hasLocalArchetype () &&
142158 !IGF.outliningCanCallValueWitnesses ()) {
143- OutliningMetadataCollector collector (IGF);
159+ OutliningMetadataCollector collector (IGF, needsLayout, needsDeinit );
144160 if (T.hasArchetype ()) {
145161 collectMetadataForOutlining (collector, T);
146162 }
@@ -150,7 +166,7 @@ bool TypeInfo::withMetadataCollector(
150166
151167 if (!T.hasArchetype ()) {
152168 // The implementation will call vwt in this case.
153- OutliningMetadataCollector collector (IGF);
169+ OutliningMetadataCollector collector (IGF, needsLayout, needsDeinit );
154170 invocation (collector);
155171 return true ;
156172 }
@@ -161,9 +177,11 @@ bool TypeInfo::withMetadataCollector(
161177void TypeInfo::callOutlinedCopy (IRGenFunction &IGF, Address dest, Address src,
162178 SILType T, IsInitialization_t isInit,
163179 IsTake_t isTake) const {
164- if (withMetadataCollector (IGF, T, [&](auto collector) {
165- collector.emitCallToOutlinedCopy (dest, src, T, *this , isInit, isTake);
166- })) {
180+ if (withMetadataCollector (IGF, T, LayoutIsNeeded, DeinitIsNotNeeded,
181+ [&](auto collector) {
182+ collector.emitCallToOutlinedCopy (
183+ dest, src, T, *this , isInit, isTake);
184+ })) {
167185 return ;
168186 }
169187
@@ -183,6 +201,8 @@ void OutliningMetadataCollector::emitCallToOutlinedCopy(
183201 Address dest, Address src,
184202 SILType T, const TypeInfo &ti,
185203 IsInitialization_t isInit, IsTake_t isTake) const {
204+ assert (needsLayout);
205+ assert (!needsDeinit);
186206 llvm::SmallVector<llvm::Value *, 4 > args;
187207 args.push_back (IGF.Builder .CreateElementBitCast (src, ti.getStorageType ())
188208 .getAddress ());
@@ -356,9 +376,10 @@ void TypeInfo::callOutlinedDestroy(IRGenFunction &IGF,
356376 if (IGF.IGM .getTypeLowering (T).isTrivial ())
357377 return ;
358378
359- if (withMetadataCollector (IGF, T, [&](auto collector) {
360- collector.emitCallToOutlinedDestroy (addr, T, *this );
361- })) {
379+ if (withMetadataCollector (
380+ IGF, T, LayoutIsNeeded, DeinitIsNeeded, [&](auto collector) {
381+ collector.emitCallToOutlinedDestroy (addr, T, *this );
382+ })) {
362383 return ;
363384 }
364385
@@ -367,6 +388,8 @@ void TypeInfo::callOutlinedDestroy(IRGenFunction &IGF,
367388
368389void OutliningMetadataCollector::emitCallToOutlinedDestroy (
369390 Address addr, SILType T, const TypeInfo &ti) const {
391+ assert (needsLayout);
392+ assert (needsDeinit);
370393 llvm::SmallVector<llvm::Value *, 4 > args;
371394 args.push_back (IGF.Builder .CreateElementBitCast (addr, ti.getStorageType ())
372395 .getAddress ());
@@ -439,24 +462,46 @@ llvm::Constant *IRGenModule::getOrCreateRetainFunction(const TypeInfo &ti,
439462 true /* setIsNoInline*/ );
440463}
441464
442- llvm::Constant *
443- IRGenModule::getOrCreateReleaseFunction (const TypeInfo &ti,
444- SILType t,
445- llvm::Type *llvmType,
446- Atomicity atomicity) {
465+ void TypeInfo::callOutlinedRelease (IRGenFunction &IGF, Address addr, SILType T,
466+ Atomicity atomicity) const {
467+ OutliningMetadataCollector collector (IGF, LayoutIsNotNeeded, DeinitIsNeeded);
468+ collectMetadataForOutlining (collector, T);
469+ collector.emitCallToOutlinedRelease (addr, T, *this , atomicity);
470+ }
471+
472+ void OutliningMetadataCollector::emitCallToOutlinedRelease (
473+ Address addr, SILType T, const TypeInfo &ti, Atomicity atomicity) const {
474+ assert (!needsLayout);
475+ assert (needsDeinit);
476+ llvm::SmallVector<llvm::Value *, 4 > args;
477+ args.push_back (addr.getAddress ());
478+ addMetadataArguments (args);
479+ auto *outlinedF = cast<llvm::Function>(IGF.IGM .getOrCreateReleaseFunction (
480+ ti, T, addr.getAddress ()->getType (), atomicity, *this ));
481+ llvm::CallInst *call =
482+ IGF.Builder .CreateCall (outlinedF->getFunctionType (), outlinedF, args);
483+ call->setCallingConv (IGF.IGM .DefaultCC );
484+ }
485+
486+ llvm::Constant *IRGenModule::getOrCreateReleaseFunction (
487+ const TypeInfo &ti, SILType t, llvm::Type *ptrTy, Atomicity atomicity,
488+ const OutliningMetadataCollector &collector) {
447489 auto *loadableTI = cast<LoadableTypeInfo>(&ti);
448490 IRGenMangler mangler;
449491 auto manglingBits =
450492 getTypeAndGenericSignatureForManglingOutlineFunction (t);
451493 auto funcName = mangler.mangleOutlinedReleaseFunction (manglingBits.first ,
452494 manglingBits.second );
453- llvm::Type *argTys[] = {llvmType};
495+ llvm::SmallVector<llvm::Type *, 4 > argTys;
496+ argTys.push_back (ptrTy);
497+ collector.addMetadataParameterTypes (argTys);
454498 return getOrCreateHelperFunction (
455- funcName, llvmType , argTys,
499+ funcName, ptrTy , argTys,
456500 [&](IRGenFunction &IGF) {
457- auto it = IGF.CurFn -> arg_begin ();
458- Address addr (&*it++ , loadableTI->getStorageType (),
501+ Explosion params = IGF.collectParameters ();
502+ Address addr (params. claimNext () , loadableTI->getStorageType (),
459503 loadableTI->getFixedAlignment ());
504+ collector.bindMetadataParameters (IGF, params);
460505 Explosion loaded;
461506 loadableTI->loadAsTake (IGF, addr, loaded);
462507 loadableTI->consume (IGF, loaded, atomicity, t);
0 commit comments