@@ -114,12 +114,23 @@ static bool shouldProfile(SILDeclRef Constant) {
114114 }
115115 }
116116
117- // Do not profile AST nodes in unavailable contexts.
118117 if (auto *D = DC->getInnermostDeclarationDeclContext ()) {
118+ // Do not profile AST nodes in unavailable contexts.
119119 if (D->getSemanticUnavailableAttr ()) {
120120 LLVM_DEBUG (llvm::dbgs () << " Skipping ASTNode: unavailable context\n " );
121121 return false ;
122122 }
123+
124+ // Do not profile functions that have had their bodies replaced (e.g
125+ // function body macros).
126+ // TODO: If/when preamble macros become an official feature, we'll
127+ // need to be more nuanced here.
128+ if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
129+ if (AFD->getOriginalBodySourceRange () != AFD->getBodySourceRange ()) {
130+ LLVM_DEBUG (llvm::dbgs () << " Skipping function: body replaced\n " );
131+ return false ;
132+ }
133+ }
123134 }
124135
125136 // Do not profile code that hasn't been written by the user.
@@ -247,9 +258,12 @@ bool shouldSkipExpr(Expr *E) {
247258// / Whether the children of a decl that isn't explicitly handled should be
248259// / walked.
249260static bool shouldWalkIntoUnhandledDecl (const Decl *D) {
250- // We want to walk into the initializer for a pattern binding decl. This
251- // allows us to map LazyInitializerExprs.
252- return isa<PatternBindingDecl>(D);
261+ // We want to walk into initializers for bindings, and the expansions of
262+ // MacroExpansionDecls, which will be nested within MacroExpansionExprs in
263+ // local contexts. We won't record any regions within the macro expansion,
264+ // but still need to walk to get accurate counter information in case e.g
265+ // there's a throwing function call in the expansion.
266+ return isa<PatternBindingDecl>(D) || isa<MacroExpansionDecl>(D);
253267}
254268
255269// / Whether the expression \c E could potentially throw an error.
@@ -468,6 +482,10 @@ class SourceMappingRegion {
468482 // / The region's ending location.
469483 std::optional<SourceLoc> EndLoc;
470484
485+ // / Whether the region is within a macro expansion. Such regions do not
486+ // / get recorded, but are needed to track the counters within the expansion.
487+ bool IsInMacroExpansion = false ;
488+
471489 SourceMappingRegion (Kind RegionKind, std::optional<CounterExpr> Counter,
472490 std::optional<SourceLoc> StartLoc)
473491 : RegionKind(RegionKind), Counter(Counter), StartLoc(StartLoc) {
@@ -516,6 +534,14 @@ class SourceMappingRegion {
516534 SourceMappingRegion (SourceMappingRegion &&Region) = default ;
517535 SourceMappingRegion &operator =(SourceMappingRegion &&RHS) = default ;
518536
537+ bool isInMacroExpansion () const {
538+ return IsInMacroExpansion;
539+ }
540+
541+ void setIsInMacroExpansion () {
542+ IsInMacroExpansion = true ;
543+ }
544+
519545 // / Whether this region is for scoping only.
520546 bool isForScopingOnly () const { return RegionKind == Kind::ScopingOnly; }
521547
@@ -810,6 +836,7 @@ struct PGOMapping : public ASTWalker {
810836struct CoverageMapping : public ASTWalker {
811837private:
812838 const SourceManager &SM;
839+ SourceFile *SF;
813840
814841 // / The SIL function being profiled.
815842 SILDeclRef Constant;
@@ -836,6 +863,12 @@ struct CoverageMapping : public ASTWalker {
836863
837864 Stmt *ImplicitTopLevelBody = nullptr ;
838865
866+ // / The number of parent MacroExpansionExprs.
867+ unsigned MacroDepth = 0 ;
868+
869+ // / Whether the current walk is within a macro expansion.
870+ bool isInMacroExpansion () const { return MacroDepth > 0 ; }
871+
839872 // / Return true if \c Ref has an associated counter.
840873 bool hasCounter (ProfileCounterRef Ref) { return CounterExprs.count (Ref); }
841874
@@ -992,6 +1025,10 @@ struct CoverageMapping : public ASTWalker {
9921025
9931026 // / Push a region onto the stack.
9941027 void pushRegion (SourceMappingRegion Region) {
1028+ // Note on the region whether we're currently in a macro expansion.
1029+ if (isInMacroExpansion ())
1030+ Region.setIsInMacroExpansion ();
1031+
9951032 LLVM_DEBUG ({
9961033 llvm::dbgs () << " Pushed region: " ;
9971034 Region.print (llvm::dbgs (), SM);
@@ -1026,6 +1063,11 @@ struct CoverageMapping : public ASTWalker {
10261063 llvm::dbgs () << " \n " ;
10271064 });
10281065
1066+ // Don't record regions in macro expansions, they don't have source
1067+ // locations that can be meaningfully mapped to source code.
1068+ if (Region.isInMacroExpansion ())
1069+ return ;
1070+
10291071 // Don't bother recording regions that are only present for scoping.
10301072 if (Region.isForScopingOnly ())
10311073 return ;
@@ -1111,9 +1153,10 @@ struct CoverageMapping : public ASTWalker {
11111153
11121154public:
11131155 CoverageMapping (
1114- const SourceManager &SM , SILDeclRef Constant,
1156+ SourceFile *SF , SILDeclRef Constant,
11151157 const llvm::DenseMap<ProfileCounterRef, unsigned > &ConcreteCounters)
1116- : SM(SM), Constant(Constant), ConcreteCounters(ConcreteCounters) {}
1158+ : SM(SF->getASTContext ().SourceMgr), SF(SF), Constant(Constant),
1159+ ConcreteCounters(ConcreteCounters) {}
11171160
11181161 LazyInitializerWalking getLazyInitializerWalkingBehavior () override {
11191162 // We want to walk lazy initializers present in the synthesized getter for
@@ -1135,20 +1178,33 @@ struct CoverageMapping : public ASTWalker {
11351178 // / source regions.
11361179 SILCoverageMap *emitSourceRegions (SILModule &M, StringRef Name,
11371180 StringRef PGOFuncName, uint64_t Hash,
1138- SourceFile *SF, StringRef Filename) {
1181+ StringRef Filename) {
11391182 if (SourceRegions.empty ())
11401183 return nullptr ;
11411184
1142- using MappedRegion = SILCoverageMap::MappedRegion;
1185+ auto FileSourceRange = SM.getRangeForBuffer (*SF->getBufferID ());
1186+ auto isLocInFile = [&](SourceLoc Loc) {
1187+ return FileSourceRange.contains (Loc) || FileSourceRange.getEnd () == Loc;
1188+ };
11431189
1190+ using MappedRegion = SILCoverageMap::MappedRegion;
11441191 std::vector<MappedRegion> Regions;
11451192 SourceRange OuterRange;
11461193 for (const auto &Region : SourceRegions) {
11471194 assert (Region.hasStartLoc () && " invalid region" );
11481195 assert (Region.hasEndLoc () && " incomplete region" );
11491196
1150- // Build up the outer range from the union of all coverage regions.
11511197 SourceRange Range (Region.getStartLoc (), Region.getEndLoc ());
1198+
1199+ // Make sure we haven't ended up with any source locations outside the
1200+ // SourceFile (e.g for generated code such as macros), asserting in an
1201+ // asserts build, dropping in a non-asserts build.
1202+ if (!isLocInFile (Range.Start ) || !isLocInFile (Range.End )) {
1203+ assert (false && " range outside of file" );
1204+ continue ;
1205+ }
1206+
1207+ // Build up the outer range from the union of all coverage regions.
11521208 if (!OuterRange) {
11531209 OuterRange = Range;
11541210 } else {
@@ -1520,10 +1576,14 @@ struct CoverageMapping : public ASTWalker {
15201576
15211577 if (hasCounter (E)) {
15221578 pushRegion (SourceMappingRegion::forNode (E, SM));
1523- } else if (isa<OptionalTryExpr>(E)) {
1579+ } else if (isa<OptionalTryExpr>(E) || isa<MacroExpansionExpr>(E) ) {
15241580 // If we have a `try?`, that doesn't already have a counter, record it
15251581 // as a scoping-only region. We need it to scope child error branches,
15261582 // but don't need it in the resulting set of regions.
1583+ //
1584+ // If we have a macro expansion, also push a scoping-only region. We'll
1585+ // discard any regions recorded within the macro, but will adjust for any
1586+ // control flow that may have happened within the macro.
15271587 assignCounter (E, getCurrentCounter ());
15281588 pushRegion (SourceMappingRegion::scopingOnly (E, SM));
15291589 }
@@ -1558,6 +1618,10 @@ struct CoverageMapping : public ASTWalker {
15581618 // Already visited the children.
15591619 return Action::SkipChildren (TE);
15601620 }
1621+
1622+ if (isa<MacroExpansionExpr>(E))
1623+ MacroDepth += 1 ;
1624+
15611625 return shouldWalkIntoExpr (E, Parent, Constant);
15621626 }
15631627
@@ -1574,6 +1638,11 @@ struct CoverageMapping : public ASTWalker {
15741638 Lexer::getLocForEndOfToken (SM, E->getEndLoc ()));
15751639 }
15761640
1641+ if (isa<MacroExpansionExpr>(E)) {
1642+ assert (isInMacroExpansion ());
1643+ MacroDepth -= 1 ;
1644+ }
1645+
15771646 if (hasCounter (E))
15781647 exitRegion (E);
15791648
@@ -1610,7 +1679,6 @@ static void walkNode(NodeToProfile Node, ASTWalker &Walker) {
16101679}
16111680
16121681void SILProfiler::assignRegionCounters () {
1613- const auto &SM = M.getASTContext ().SourceMgr ;
16141682 auto *DC = forDecl.getInnermostDeclContext ();
16151683 auto *SF = DC->getParentSourceFile ();
16161684 assert (SF && " Not within a SourceFile?" );
@@ -1647,10 +1715,10 @@ void SILProfiler::assignRegionCounters() {
16471715 PGOFuncHash = 0x0 ;
16481716
16491717 if (EmitCoverageMapping) {
1650- CoverageMapping Coverage (SM , forDecl, RegionCounterMap);
1718+ CoverageMapping Coverage (SF , forDecl, RegionCounterMap);
16511719 walkNode (Root, Coverage);
16521720 CovMap = Coverage.emitSourceRegions (M, CurrentFuncName, PGOFuncName,
1653- PGOFuncHash, SF, CurrentFileName);
1721+ PGOFuncHash, CurrentFileName);
16541722 }
16551723
16561724 if (llvm::IndexedInstrProfReader *IPR = M.getPGOReader ()) {
0 commit comments