@@ -94,6 +94,10 @@ class PerformanceDiagnostics {
9494 return visitFunction (function, perfConstr, /* parentLoc*/ nullptr );
9595 }
9696
97+ bool visitFunctionEmbeddedSwift (SILFunction *function) {
98+ return visitFunctionEmbeddedSwift (function, /* parentLoc*/ nullptr );
99+ }
100+
97101 // / Check functions _without_ performance annotations.
98102 // /
99103 // / This is need to check closure arguments of called performance-annotated
@@ -104,6 +108,9 @@ class PerformanceDiagnostics {
104108 bool visitFunction (SILFunction *function, PerformanceConstraints perfConstr,
105109 LocWithParent *parentLoc);
106110
111+ bool visitFunctionEmbeddedSwift (SILFunction *function,
112+ LocWithParent *parentLoc);
113+
107114 bool visitInst (SILInstruction *inst, PerformanceConstraints perfConstr,
108115 LocWithParent *parentLoc);
109116
@@ -150,6 +157,75 @@ static bool isEffectFreeArraySemanticCall(SILInstruction *inst) {
150157 }
151158}
152159
160+ // / Prints Embedded Swift specific performance diagnostics (no existentials,
161+ // / no metatypes, optionally no allocations) for \p function.
162+ bool PerformanceDiagnostics::visitFunctionEmbeddedSwift (
163+ SILFunction *function, LocWithParent *parentLoc) {
164+ // Don't check generic functions in embedded Swift, they're about to be
165+ // removed anyway.
166+ if (function->getLoweredFunctionType ()->getSubstGenericSignature ())
167+ return false ;
168+
169+ if (!function->isDefinition ())
170+ return false ;
171+
172+ if (visitedFuncs.contains (function))
173+ return false ;
174+ visitedFuncs[function] = PerformanceConstraints::None;
175+
176+ NonErrorHandlingBlocks neBlocks (function);
177+
178+ for (SILBasicBlock &block : *function) {
179+ for (SILInstruction &inst : block) {
180+ if (visitInst (&inst, PerformanceConstraints::None, parentLoc)) {
181+ if (inst.getLoc ().getSourceLoc ().isInvalid ()) {
182+ auto demangledName = Demangle::demangleSymbolAsString (
183+ inst.getFunction ()->getName (),
184+ Demangle::DemangleOptions::SimplifiedUIDemangleOptions ());
185+ llvm::errs () << " in function " << demangledName << " \n " ;
186+ }
187+ LLVM_DEBUG (llvm::dbgs () << inst << *inst.getFunction ());
188+ return true ;
189+ }
190+
191+ if (auto as = FullApplySite::isa (&inst)) {
192+ LocWithParent asLoc (inst.getLoc ().getSourceLoc (), parentLoc);
193+ LocWithParent *loc = &asLoc;
194+ if (parentLoc &&
195+ asLoc.loc == inst.getFunction ()->getLocation ().getSourceLoc ())
196+ loc = parentLoc;
197+
198+ for (SILFunction *callee : bca->getCalleeList (as)) {
199+ if (visitFunctionEmbeddedSwift (callee, loc))
200+ return true ;
201+ }
202+ } else if (auto *bi = dyn_cast<BuiltinInst>(&inst)) {
203+ PrettyStackTracePerformanceDiagnostics stackTrace (
204+ " visitFunction::BuiltinInst (once, once with context)" , &inst);
205+
206+ switch (bi->getBuiltinInfo ().ID ) {
207+ case BuiltinValueKind::Once:
208+ case BuiltinValueKind::OnceWithContext:
209+ if (auto *fri = dyn_cast<FunctionRefInst>(bi->getArguments ()[1 ])) {
210+ LocWithParent asLoc (bi->getLoc ().getSourceLoc (), parentLoc);
211+ LocWithParent *loc = &asLoc;
212+ if (parentLoc &&
213+ asLoc.loc == bi->getFunction ()->getLocation ().getSourceLoc ())
214+ loc = parentLoc;
215+
216+ if (visitFunctionEmbeddedSwift (fri->getReferencedFunction (), loc))
217+ return true ;
218+ }
219+ break ;
220+ default :
221+ break ;
222+ }
223+ }
224+ }
225+ }
226+ return false ;
227+ }
228+
153229// / Prints performance diagnostics for \p function.
154230bool PerformanceDiagnostics::visitFunction (SILFunction *function,
155231 PerformanceConstraints perfConstr,
@@ -438,6 +514,18 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
438514 return true ;
439515 }
440516 }
517+
518+ if (module .getOptions ().NoAllocations ) {
519+ if (impact & RuntimeEffect::Allocating) {
520+ PrettyStackTracePerformanceDiagnostics stackTrace (" allocation" , inst);
521+ if (impactType) {
522+ diagnose (loc, diag::embedded_swift_allocating_type, impactType.getASTType ());
523+ } else {
524+ diagnose (loc, diag::embedded_swift_allocating);
525+ }
526+ return true ;
527+ }
528+ }
441529 }
442530
443531 if (perfConstr == PerformanceConstraints::None ||
@@ -585,19 +673,6 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
585673void PerformanceDiagnostics::checkNonAnnotatedFunction (SILFunction *function) {
586674 for (SILBasicBlock &block : *function) {
587675 for (SILInstruction &inst : block) {
588- if (function->getModule ().getOptions ().EmbeddedSwift ) {
589- auto loc = LocWithParent (inst.getLoc ().getSourceLoc (), nullptr );
590- if (visitInst (&inst, PerformanceConstraints::None, &loc)) {
591- if (inst.getLoc ().getSourceLoc ().isInvalid ()) {
592- auto demangledName = Demangle::demangleSymbolAsString (
593- inst.getFunction ()->getName (),
594- Demangle::DemangleOptions::SimplifiedUIDemangleOptions ());
595- llvm::errs () << " in function " << demangledName << " \n " ;
596- }
597- LLVM_DEBUG (llvm::dbgs () << inst << *inst.getFunction ());
598- }
599- }
600-
601676 auto as = FullApplySite::isa (&inst);
602677 if (!as)
603678 continue ;
@@ -701,16 +776,54 @@ class PerformanceDiagnosticsPass : public SILModuleTransform {
701776 if (function.wasDeserializedCanonical ())
702777 continue ;
703778
704- // Don't check generic functions in embedded Swift, they're about to be
705- // removed anyway.
706- if (getModule ()->getOptions ().EmbeddedSwift &&
707- function.getLoweredFunctionType ()->getSubstGenericSignature ())
708- continue ;
709-
710779 if (function.getPerfConstraints () == PerformanceConstraints::None) {
711780 diagnoser.checkNonAnnotatedFunction (&function);
712781 }
713782 }
783+
784+ if (getModule ()->getOptions ().EmbeddedSwift ) {
785+ // Run embedded Swift SIL checks for metatype/existential use, and
786+ // allocation use (under -no-allocations mode). Try to start with public
787+ // and exported functions to get better call tree information.
788+ SmallVector<SILFunction *, 8 > externallyVisibleFunctions;
789+ SmallVector<SILFunction *, 8 > vtableMembers;
790+ SmallVector<SILFunction *, 8 > others;
791+ SmallVector<SILFunction *, 8 > constructorsAndDestructors;
792+
793+ for (SILFunction &function : *module ) {
794+ auto func = function.getLocation ().getAsASTNode <AbstractFunctionDecl>();
795+ if (func) {
796+ if (isa<DestructorDecl>(func) || isa<ConstructorDecl>(func)) {
797+ constructorsAndDestructors.push_back (&function);
798+ continue ;
799+ }
800+ if (getMethodDispatch (func) == MethodDispatch::Class) {
801+ vtableMembers.push_back (&function);
802+ continue ;
803+ }
804+ }
805+
806+ if (function.isPossiblyUsedExternally ()) {
807+ externallyVisibleFunctions.push_back (&function);
808+ continue ;
809+ }
810+
811+ others.push_back (&function);
812+ }
813+
814+ for (SILFunction *function : externallyVisibleFunctions) {
815+ diagnoser.visitFunctionEmbeddedSwift (function);
816+ }
817+ for (SILFunction *function : vtableMembers) {
818+ diagnoser.visitFunctionEmbeddedSwift (function);
819+ }
820+ for (SILFunction *function : others) {
821+ diagnoser.visitFunctionEmbeddedSwift (function);
822+ }
823+ for (SILFunction *function : constructorsAndDestructors) {
824+ diagnoser.visitFunctionEmbeddedSwift (function);
825+ }
826+ }
714827 }
715828};
716829
0 commit comments