@@ -71,7 +71,10 @@ struct ValueToDeclInferrer {
7171
7272void ValueToDeclInferrer::printNote (llvm::raw_string_ostream &stream,
7373 const ValueDecl *decl) {
74+ assert (decl &&
75+ " We assume for now that this is always called with a non-null decl" );
7476 stream << " of '" << decl->getBaseName ();
77+
7578 for (auto &pair : accessPath) {
7679 auto baseType = pair.first ;
7780 auto &proj = pair.second ;
@@ -133,6 +136,12 @@ static SingleValueInstruction *isSupportedProjection(Projection p, SILValue v) {
133136 llvm_unreachable (" Covered switch is not covered?!" );
134137}
135138
139+ static bool hasNonInlinedDebugScope (SILInstruction *i) {
140+ if (auto *scope = i->getDebugScope ())
141+ return !scope->InlinedCallSite ;
142+ return false ;
143+ }
144+
136145bool ValueToDeclInferrer::infer (
137146 ArgumentKeyKind keyKind, SILValue value,
138147 SmallVectorImpl<Argument> &resultingInferredDecls) {
@@ -167,6 +176,46 @@ bool ValueToDeclInferrer::infer(
167176 return true ;
168177 }
169178
179+ if (auto *ari = dyn_cast<AllocRefInst>(value)) {
180+ if (auto *decl = ari->getDecl ()) {
181+ std::string msg;
182+ {
183+ llvm::raw_string_ostream stream (msg);
184+ printNote (stream, decl);
185+ }
186+ resultingInferredDecls.push_back (
187+ Argument ({keyKind, " InferredValue" }, std::move (msg), decl));
188+ return true ;
189+ }
190+ }
191+
192+ if (auto *abi = dyn_cast<AllocBoxInst>(value)) {
193+ if (auto *decl = abi->getDecl ()) {
194+ std::string msg;
195+ {
196+ llvm::raw_string_ostream stream (msg);
197+ printNote (stream, decl);
198+ }
199+
200+ resultingInferredDecls.push_back (
201+ Argument ({keyKind, " InferredValue" }, std::move (msg), decl));
202+ return true ;
203+ }
204+ }
205+
206+ if (auto *asi = dyn_cast<AllocStackInst>(value)) {
207+ if (auto *decl = asi->getDecl ()) {
208+ std::string msg;
209+ {
210+ llvm::raw_string_ostream stream (msg);
211+ printNote (stream, decl);
212+ }
213+ resultingInferredDecls.push_back (
214+ Argument ({keyKind, " InferredValue" }, std::move (msg), decl));
215+ return true ;
216+ }
217+ }
218+
170219 // Then visit our users and see if we can find a debug_value that provides
171220 // us with a decl we can use to construct an argument.
172221 bool foundDeclFromUse = false ;
@@ -178,18 +227,16 @@ bool ValueToDeclInferrer::infer(
178227 if (auto *dvi = dyn_cast<DebugValueInst>(use->getUser ())) {
179228 // Check if our debug_value has a decl and was not inlined into the
180229 // current function.
181- if (auto *scope = dvi->getDebugScope ()) {
182- if (!scope->InlinedCallSite ) {
183- if (auto *decl = dvi->getDecl ()) {
184- std::string msg;
185- {
186- llvm::raw_string_ostream stream (msg);
187- printNote (stream, decl);
188- }
189- resultingInferredDecls.push_back (
190- Argument ({keyKind, " InferredValue" }, std::move (msg), decl));
191- foundDeclFromUse = true ;
230+ if (hasNonInlinedDebugScope (dvi)) {
231+ if (auto *decl = dvi->getDecl ()) {
232+ std::string msg;
233+ {
234+ llvm::raw_string_ostream stream (msg);
235+ printNote (stream, decl);
192236 }
237+ resultingInferredDecls.push_back (
238+ Argument ({keyKind, " InferredValue" }, std::move (msg), decl));
239+ foundDeclFromUse = true ;
193240 }
194241 }
195242 }
@@ -216,6 +263,8 @@ bool ValueToDeclInferrer::infer(
216263 }
217264 }
218265
266+ // TODO: We could emit at this point a msg for temporary allocations.
267+
219268 // If we reached this point, we finished falling through the loop and return
220269 // true.
221270 return true ;
@@ -245,6 +294,8 @@ struct OptRemarkGeneratorInstructionVisitor
245294 void visitStrongReleaseInst (StrongReleaseInst *sri);
246295 void visitRetainValueInst (RetainValueInst *rvi);
247296 void visitReleaseValueInst (ReleaseValueInst *rvi);
297+ void visitAllocRefInst (AllocRefInst *ari);
298+ void visitAllocBoxInst (AllocBoxInst *abi);
248299 void visitSILInstruction (SILInstruction *) {}
249300};
250301
@@ -333,6 +384,64 @@ void OptRemarkGeneratorInstructionVisitor::visitReleaseValueInst(
333384 });
334385}
335386
387+ void OptRemarkGeneratorInstructionVisitor::visitAllocRefInst (
388+ AllocRefInst *ari) {
389+ if (ari->canAllocOnStack ()) {
390+ return ORE.emit ([&]() {
391+ using namespace OptRemark ;
392+ SmallVector<Argument, 8 > inferredArgs;
393+ bool foundArgs =
394+ valueToDeclInferrer.infer (ArgumentKeyKind::Note, ari, inferredArgs);
395+ (void )foundArgs;
396+ auto resultRemark =
397+ RemarkPassed (" memory" , *ari,
398+ SourceLocInferenceBehavior::ForwardScanOnly)
399+ << " stack allocated ref of type '" << NV (" ValueType" , ari->getType ())
400+ << " '" ;
401+ for (auto &arg : inferredArgs)
402+ resultRemark << arg;
403+ return resultRemark;
404+ });
405+ }
406+
407+ return ORE.emit ([&]() {
408+ using namespace OptRemark ;
409+ SmallVector<Argument, 8 > inferredArgs;
410+ bool foundArgs =
411+ valueToDeclInferrer.infer (ArgumentKeyKind::Note, ari, inferredArgs);
412+ (void )foundArgs;
413+
414+ auto resultRemark =
415+ RemarkMissed (" memory" , *ari,
416+ SourceLocInferenceBehavior::ForwardScanOnly)
417+ << " heap allocated ref of type '" << NV (" ValueType" , ari->getType ())
418+ << " '" ;
419+ for (auto &arg : inferredArgs)
420+ resultRemark << arg;
421+ return resultRemark;
422+ });
423+ }
424+
425+ void OptRemarkGeneratorInstructionVisitor::visitAllocBoxInst (
426+ AllocBoxInst *abi) {
427+ return ORE.emit ([&]() {
428+ using namespace OptRemark ;
429+ SmallVector<Argument, 8 > inferredArgs;
430+ bool foundArgs =
431+ valueToDeclInferrer.infer (ArgumentKeyKind::Note, abi, inferredArgs);
432+ (void )foundArgs;
433+
434+ auto resultRemark =
435+ RemarkMissed (" memory" , *abi,
436+ SourceLocInferenceBehavior::ForwardScanOnly)
437+ << " heap allocated box of type '" << NV (" ValueType" , abi->getType ())
438+ << " '" ;
439+ for (auto &arg : inferredArgs)
440+ resultRemark << arg;
441+ return resultRemark;
442+ });
443+ }
444+
336445// ===----------------------------------------------------------------------===//
337446// Top Level Entrypoint
338447// ===----------------------------------------------------------------------===//
0 commit comments