Skip to content

Commit 398d07f

Browse files
authored
Merge pull request swiftlang#38321 from gottesmm/pr-133b8c9dd74d4509715057594806f34d67caf2a0
[assembly-vision] If a nominal type is marked with @_assemblyVision emit AssemblyVisionRemarks for all of the nominal type's methods.
2 parents 0057c65 + 79211d4 commit 398d07f

File tree

5 files changed

+115
-11
lines changed

5 files changed

+115
-11
lines changed

include/swift/AST/Attr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ SIMPLE_DECL_ATTR(_distributedActorIndependent, DistributedActorIndependent,
673673
119)
674674

675675
SIMPLE_DECL_ATTR(_assemblyVision, EmitAssemblyVisionRemarks,
676-
OnFunc | UserInaccessible | NotSerialized |
676+
OnFunc | UserInaccessible | NotSerialized | OnNominalType |
677677
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
678678
120)
679679

include/swift/AST/Decl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3279,6 +3279,12 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
32793279
return getAttrs().hasSemanticsAttr(attrValue);
32803280
}
32813281

3282+
/// Returns true if we should emit assembly vision remarks on all methods of
3283+
/// this nominal type.
3284+
bool shouldEmitAssemblyVisionRemarksOnMethods() const {
3285+
return getAttrs().hasAttribute<EmitAssemblyVisionRemarksAttr>();
3286+
}
3287+
32823288
/// Whether this declaration has a synthesized memberwise initializer.
32833289
bool hasMemberwiseInitializer() const;
32843290

lib/SIL/Utils/OptimizationRemark.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,28 @@ static bool hasForceEmitSemanticAttr(SILFunction &fn, StringRef passName) {
135135
});
136136
}
137137

138+
static bool isMethodWithForceEmitSemanticAttrNominalType(SILFunction &fn) {
139+
if (!fn.hasSelfParam())
140+
return false;
141+
142+
auto selfType = fn.getSelfArgument()->getType();
143+
auto *nomType = selfType.getNominalOrBoundGenericNominal();
144+
if (!nomType)
145+
return false;
146+
return nomType->shouldEmitAssemblyVisionRemarksOnMethods();
147+
}
148+
138149
Emitter::Emitter(StringRef passName, SILFunction &fn)
139150
: fn(fn), passName(passName),
140151
passedEnabled(
141152
hasForceEmitSemanticAttr(fn, passName) ||
153+
isMethodWithForceEmitSemanticAttrNominalType(fn) ||
142154
(fn.getASTContext().LangOpts.OptimizationRemarkPassedPattern &&
143155
fn.getASTContext().LangOpts.OptimizationRemarkPassedPattern->match(
144156
passName))),
145157
missedEnabled(
146158
hasForceEmitSemanticAttr(fn, passName) ||
159+
isMethodWithForceEmitSemanticAttrNominalType(fn) ||
147160
(fn.getASTContext().LangOpts.OptimizationRemarkMissedPattern &&
148161
fn.getASTContext().LangOpts.OptimizationRemarkMissedPattern->match(
149162
passName))) {}

lib/SILOptimizer/Transforms/AssemblyVisionRemarkGenerator.cpp

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -773,11 +773,35 @@ class AssemblyVisionRemarkGenerator : public SILFunctionTransform {
773773
// TODO: Put this on LangOpts as a helper.
774774
auto &langOpts = fn->getASTContext().LangOpts;
775775

776-
return bool(langOpts.OptimizationRemarkMissedPattern) ||
777-
bool(langOpts.OptimizationRemarkPassedPattern) ||
778-
fn->getModule().getSILRemarkStreamer() ||
779-
fn->hasSemanticsAttrThatStartsWith(
780-
semantics::FORCE_EMIT_OPT_REMARK_PREFIX);
776+
// If we are supposed to emit remarks, always emit.
777+
if (bool(langOpts.OptimizationRemarkMissedPattern) ||
778+
bool(langOpts.OptimizationRemarkPassedPattern) ||
779+
fn->getModule().getSILRemarkStreamer())
780+
return true;
781+
782+
// Otherwise, first check if our function has a force emit opt remark prefix
783+
// semantics tag.
784+
if (fn->hasSemanticsAttrThatStartsWith(
785+
semantics::FORCE_EMIT_OPT_REMARK_PREFIX))
786+
return true;
787+
788+
// Otherwise, check if we have a self parameter that is a nominal type that
789+
// is marked with the @_assemblyVision attribute.
790+
if (fn->hasSelfParam()) {
791+
if (auto *nomType = fn->getSelfArgument()
792+
->getType()
793+
.getNominalOrBoundGenericNominal()) {
794+
LLVM_DEBUG(llvm::dbgs() << "Checking for remark on: "
795+
<< nomType->getName().get() << "\n");
796+
if (nomType->shouldEmitAssemblyVisionRemarksOnMethods()) {
797+
LLVM_DEBUG(llvm::dbgs() << "Success! Will emit remarks!!\n");
798+
return true;
799+
}
800+
LLVM_DEBUG(llvm::dbgs() << "Fail! No remarks will be emitted!!\n");
801+
}
802+
}
803+
804+
return false;
781805
}
782806

783807
/// The entry point to the transformation.
@@ -791,14 +815,24 @@ class AssemblyVisionRemarkGenerator : public SILFunctionTransform {
791815
// unless we were asked by the user to emit them.
792816
if (!ForceVisitImplicitAutogeneratedFunctions) {
793817
// Skip implicit functions generated by Sema.
794-
if (auto *ctx = fn->getDeclContext())
795-
if (auto *decl = ctx->getAsDecl())
796-
if (decl->isImplicit())
818+
if (auto *ctx = fn->getDeclContext()) {
819+
if (auto *decl = ctx->getAsDecl()) {
820+
if (decl->isImplicit()) {
821+
LLVM_DEBUG(llvm::dbgs() << "Skipping implicit decl function: "
822+
<< fn->getName() << "\n");
797823
return;
824+
}
825+
}
826+
}
827+
798828
// Skip autogenerated functions generated by SILGen.
799-
if (auto loc = fn->getDebugScope()->getLoc())
800-
if (loc.isAutoGenerated())
829+
if (auto loc = fn->getDebugScope()->getLoc()) {
830+
if (loc.isAutoGenerated()) {
831+
LLVM_DEBUG(llvm::dbgs() << "Skipping autogenerated function: "
832+
<< fn->getName() << "\n");
801833
return;
834+
}
835+
}
802836
}
803837

804838
LLVM_DEBUG(llvm::dbgs() << "Visiting: " << fn->getName() << "\n");
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: %target-swiftc_driver -Osize -emit-sil %s -o /dev/null -Xfrontend -verify
2+
// REQUIRES: optimized_stdlib,swift_stdlib_no_asserts
3+
4+
// Make sure we emit remarks on nominal types
5+
6+
@inline(never)
7+
func callPrint(_ s: String) { print(s) }
8+
9+
var global: String = "123"
10+
11+
@_assemblyVision
12+
struct Struct {
13+
func printMe() {
14+
callPrint(global) // expected-remark {{begin exclusive access to value of type '}}
15+
// expected-note @-6 {{of 'global'}}
16+
// expected-remark @-2 {{end exclusive access to value of type '}}
17+
// expected-note @-8 {{of 'global'}}
18+
// expected-remark @-4 {{retain of type '}}
19+
// expected-note @-10 {{of 'global'}}
20+
// expected-remark @-6 {{release of type '}}
21+
// expected-note @-12 {{of 'global}}
22+
}
23+
}
24+
25+
// Negative test
26+
struct Struct2 {
27+
func callPrintMe() {
28+
callPrint(global)
29+
}
30+
}
31+
32+
@_assemblyVision
33+
enum Enum {
34+
func callPrintMe() {
35+
callPrint(global) // expected-remark {{begin exclusive access to value of type '}}
36+
// expected-note @-27 {{of 'global'}}
37+
// expected-remark @-2 {{end exclusive access to value of type '}}
38+
// expected-note @-29 {{of 'global'}}
39+
// expected-remark @-4 {{retain of type '}}
40+
// expected-note @-31 {{of 'global'}}
41+
// expected-remark @-6 {{release of type '}}
42+
// expected-note @-33 {{of 'global}}
43+
}
44+
}
45+
46+
// Negative test
47+
enum Enum2 {
48+
func callPrintMe() {
49+
callPrint("I am callPrinting 1")
50+
}
51+
}

0 commit comments

Comments
 (0)