Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3479778

Browse files
sbomerpull[bot]
authored andcommitted
Add ILLink/ILCompiler support for feature checks (#99267)
This will substitute static boolean properties with `false` whendecorated with `[FeatureGuard(typeof(SomeFeature))]`, where`SomeFeature` is known to be disabled.The "feature" of unreferenced code, represented by`RequiresUnreferencedCodeAttribute`, is always considereddisabled. For ILC, `RequiresDynamicCodeAttribute` and`RequiresAssemblyFilesAttribute` are also disabled. ILLink alsorespects the feature switch for `IsDynamicCodeSupported` todisable the `RequiresDynamicCodeAttribute` feature.We don't want this kicking in when trimming in library mode, sothis adds an ILLink option to disable the optimization.Additionally, a property is substituted if it has`[FeatureSwitchDefinition("SomeFeatureName")]` and`"SomeFeatureName"` is set in the command-line arguments.XML substitutions take precedence over this behavior.Includes a few tweaks and cleanup to the analyzer logic.
1 parent49ae287 commit3479778

File tree

23 files changed

+794
-199
lines changed

23 files changed

+794
-199
lines changed

‎src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/SubstitutionProvider.cs‎

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
usingSystem;
55
usingSystem.Collections.Generic;
66
usingSystem.IO;
7+
usingSystem.Reflection;
78
usingSystem.Reflection.Metadata;
89
usingSystem.Reflection.PortableExecutable;
910
usingSystem.Resources;
@@ -33,11 +34,84 @@ public BodySubstitution GetSubstitution(MethodDesc method)
3334
AssemblyFeatureInfoinfo=_hashtable.GetOrCreateValue(ecmaMethod.Module);
3435
if(info.BodySubstitutions!=null&&info.BodySubstitutions.TryGetValue(ecmaMethod,outBodySubstitutionresult))
3536
returnresult;
37+
38+
if(TryGetFeatureCheckValue(ecmaMethod,outboolvalue))
39+
returnBodySubstitution.Create(value?1:0);
3640
}
3741

3842
returnnull;
3943
}
4044

45+
privateboolTryGetFeatureCheckValue(EcmaMethodmethod,outboolvalue)
46+
{
47+
value=false;
48+
49+
if(!method.Signature.IsStatic)
50+
returnfalse;
51+
52+
if(!method.Signature.ReturnType.IsWellKnownType(WellKnownType.Boolean))
53+
returnfalse;
54+
55+
if(FindProperty(method)is notPropertyPseudoDescproperty)
56+
returnfalse;
57+
58+
if(property.SetMethod!=null)
59+
returnfalse;
60+
61+
foreach(varfeatureSwitchDefinitionAttributeinproperty.GetDecodedCustomAttributes("System.Diagnostics.CodeAnalysis","FeatureSwitchDefinitionAttribute"))
62+
{
63+
if(featureSwitchDefinitionAttribute.FixedArgumentsis not[CustomAttributeTypedArgument<TypeDesc>{Value:stringswitchName}])
64+
continue;
65+
66+
// If there's a FeatureSwitchDefinition, don't continue looking for FeatureGuard.
67+
// We don't want to infer feature switch settings from FeatureGuard.
68+
return_hashtable._switchValues.TryGetValue(switchName,outvalue);
69+
}
70+
71+
foreach(varfeatureGuardAttributeinproperty.GetDecodedCustomAttributes("System.Diagnostics.CodeAnalysis","FeatureGuardAttribute"))
72+
{
73+
if(featureGuardAttribute.FixedArgumentsis not[CustomAttributeTypedArgument<TypeDesc>{Value:EcmaTypefeatureType}])
74+
continue;
75+
76+
if(featureType.Namespace=="System.Diagnostics.CodeAnalysis"){
77+
switch(featureType.Name){
78+
case"RequiresAssemblyFilesAttribute":
79+
case"RequiresUnreferencedCodeAttribute":
80+
returntrue;
81+
case"RequiresDynamicCodeAttribute":
82+
if(_hashtable._switchValues.TryGetValue(
83+
"System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported",
84+
outboolisDynamicCodeSupported)
85+
&&!isDynamicCodeSupported)
86+
returntrue;
87+
break;
88+
}
89+
}
90+
}
91+
92+
returnfalse;
93+
94+
staticPropertyPseudoDescFindProperty(EcmaMethodmethod)
95+
{
96+
if((method.Attributes&MethodAttributes.SpecialName)==0)
97+
returnnull;
98+
99+
if(method.OwningTypeis notEcmaTypedeclaringType)
100+
returnnull;
101+
102+
varreader=declaringType.MetadataReader;
103+
foreach(PropertyDefinitionHandlepropertyHandleinreader.GetTypeDefinition(declaringType.Handle).GetProperties())
104+
{
105+
PropertyDefinitionpropertyDef=reader.GetPropertyDefinition(propertyHandle);
106+
varproperty=newPropertyPseudoDesc(declaringType,propertyHandle);
107+
if(property.GetMethod==method)
108+
returnproperty;
109+
}
110+
111+
returnnull;
112+
}
113+
}
114+
41115
publicobjectGetSubstitution(FieldDescfield)
42116
{
43117
if(field.GetTypicalFieldDefinition()isEcmaFieldecmaField)

‎src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCases/TestDatabase.cs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ public static IEnumerable<object[]> SingleFile ()
6969
returnTestNamesBySuiteName();
7070
}
7171

72+
publicstaticIEnumerable<object[]>Substitutions()
73+
{
74+
returnTestNamesBySuiteName();
75+
}
76+
7277
publicstaticIEnumerable<object[]>TopLevelStatements()
7378
{
7479
returnTestNamesBySuiteName();

‎src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCases/TestSuites.cs‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,20 @@ public void SingleFile (string t)
103103
Run(t);
104104
}
105105

106+
[Theory]
107+
[MemberData(nameof(TestDatabase.Substitutions),MemberType=typeof(TestDatabase))]
108+
publicvoidSubstitutions(stringt)
109+
{
110+
switch(t){
111+
case"FeatureGuardSubstitutions":
112+
Run(t);
113+
break;
114+
default:
115+
// Skip the rest for now
116+
break;
117+
}
118+
}
119+
106120
[Theory]
107121
[MemberData(nameof(TestDatabase.TopLevelStatements),MemberType=typeof(TestDatabase))]
108122
publicvoidTopLevelStatements(stringt)

‎src/tools/illink/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ internal static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypes
7474
internalstaticValueSet<string>GetFeatureGuardAnnotations(thisIPropertySymbolpropertySymbol)
7575
{
7676
HashSet<string>featureSet=new();
77-
foreach(varattributeDatainpropertySymbol.GetAttributes(DynamicallyAccessedMembersAnalyzer.FullyQualifiedFeatureGuardAttribute)){
78-
if(attributeData.ConstructorArgumentsis[TypedConstant{Value:INamedTypeSymbolfeatureType}])
77+
foreach(varfeatureGuardAttributeinpropertySymbol.GetAttributes(DynamicallyAccessedMembersAnalyzer.FullyQualifiedFeatureGuardAttribute)){
78+
if(featureGuardAttribute.ConstructorArgumentsis[TypedConstant{Value:INamedTypeSymbolfeatureType}])
7979
featureSet.Add(featureType.GetDisplayName());
8080
}
8181
returnfeatureSet.Count==0?ValueSet<string>.Empty:newValueSet<string>(featureSet);

‎src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ protected virtual bool CreateSpecialIncompatibleMembersDiagnostic (
305305
internalstaticboolIsAnnotatedFeatureGuard(IPropertySymbolpropertySymbol,stringfeatureName)
306306
{
307307
// Only respect FeatureGuardAttribute on static boolean properties.
308-
if(!propertySymbol.IsStatic||propertySymbol.Type.SpecialType!=SpecialType.System_Boolean)
308+
if(!propertySymbol.IsStatic||propertySymbol.Type.SpecialType!=SpecialType.System_Boolean||propertySymbol.SetMethod!=null)
309309
returnfalse;
310310

311311
ValueSet<string>featureCheckAnnotations=propertySymbol.GetFeatureGuardAnnotations();

‎src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/FeatureCheckReturnValuePattern.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ public IEnumerable<Diagnostic> CollectDiagnostics (DataFlowAnalyzerContext conte
3636
if(!context.EnableTrimAnalyzer)
3737
returndiagnosticContext.Diagnostics;
3838

39-
if(!OwningSymbol.IsStatic||OwningSymbol.Type.SpecialType!=SpecialType.System_Boolean){
40-
// Warn about invalid feature checks (non-static or non-bool properties)
39+
if(!OwningSymbol.IsStatic||OwningSymbol.Type.SpecialType!=SpecialType.System_Boolean||OwningSymbol.SetMethod!=null){
40+
// Warn about invalid feature checks (non-static or non-bool properties or properties with setter)
4141
diagnosticContext.AddDiagnostic(
4242
DiagnosticId.InvalidFeatureGuard);
4343
returndiagnosticContext.Diagnostics;

‎src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ public class TrimAnalysisVisitor : LocalDataFlowVisitor<
4343

4444
FeatureChecksVisitor_featureChecksVisitor;
4545

46-
DataFlowAnalyzerContext_dataFlowAnalyzerContext;
47-
4846
publicTrimAnalysisVisitor(
4947
Compilationcompilation,
5048
LocalStateAndContextLattice<MultiValue,FeatureContext,ValueSetLattice<SingleValue>,FeatureContextLattice>lattice,
@@ -59,7 +57,6 @@ public TrimAnalysisVisitor (
5957
_multiValueLattice=lattice.LocalStateLattice.Lattice.ValueLattice;
6058
TrimAnalysisPatterns=trimAnalysisPatterns;
6159
_featureChecksVisitor=newFeatureChecksVisitor(dataFlowAnalyzerContext);
62-
_dataFlowAnalyzerContext=dataFlowAnalyzerContext;
6360
}
6461

6562
publicoverrideFeatureChecksValueGetConditionValue(IOperationbranchValueOperation,StateValuestate)
@@ -436,7 +433,8 @@ public override void HandleReturnConditionValue (FeatureChecksValue returnCondit
436433
if(OwningSymbolis notIMethodSymbolmethod)
437434
return;
438435

439-
// FeatureGuard validation needs to happen only for properties.
436+
// FeatureGuard validation needs to happen only for property getters.
437+
// Include properties with setters here because they will get validated later.
440438
if(method.MethodKind!=MethodKind.PropertyGet)
441439
return;
442440

‎src/tools/illink/src/linker/Linker.Steps/RootAssemblyInputStep.cs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ protected override void Process ()
7878
CodeOptimizations.RemoveLinkAttributes|
7979
CodeOptimizations.RemoveSubstitutions|
8080
CodeOptimizations.RemoveDynamicDependencyAttribute|
81-
CodeOptimizations.OptimizeTypeHierarchyAnnotations,assembly.Name.Name);
81+
CodeOptimizations.OptimizeTypeHierarchyAnnotations|
82+
CodeOptimizations.SubstituteFeatureGuards,assembly.Name.Name);
8283

8384
// Enable EventSource special handling
8485
Context.DisableEventSourceSpecialHandling=false;

‎src/tools/illink/src/linker/Linker/CustomAttributeSource.cs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ public bool TryGetEmbeddedXmlInfo (ICustomAttributeProvider provider, [NotNullWh
5252
returnxmlInfo!=null;
5353
}
5454

55+
publicIEnumerable<CustomAttribute>GetCustomAttributes(ICustomAttributeProviderprovider,stringattributeNamespace,stringattributeName)
56+
{
57+
foreach(varattrinGetCustomAttributes(provider)){
58+
if(attr.AttributeType.Namespace==attributeNamespace&&attr.AttributeType.Name==attributeName)
59+
yieldreturnattr;
60+
}
61+
}
62+
5563
publicIEnumerable<CustomAttribute>GetCustomAttributes(ICustomAttributeProviderprovider)
5664
{
5765
if(provider.HasCustomAttributes){

‎src/tools/illink/src/linker/Linker/Driver.cs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,9 @@ protected bool GetOptimizationName (string text, out CodeOptimizations optimizat
11791179
case"sealer":
11801180
optimization=CodeOptimizations.Sealer;
11811181
returntrue;
1182+
case"substitutefeatureguards":
1183+
optimization=CodeOptimizations.SubstituteFeatureGuards;
1184+
returntrue;
11821185
}
11831186

11841187
Context.LogError(null,DiagnosticId.InvalidOptimizationValue,text);
@@ -1361,6 +1364,7 @@ static void Usage ()
13611364
Console.WriteLine(" unreachablebodies: Instance methods that are marked but not executed are converted to throws");
13621365
Console.WriteLine(" unusedinterfaces: Removes interface types from declaration when not used");
13631366
Console.WriteLine(" unusedtypechecks: Inlines never successful type checks");
1367+
Console.WriteLine(" substitutefeatureguards: Substitutes properties annotated as FeatureGuard(typeof(RequiresUnreferencedCodeAttribute)) to false");
13641368
Console.WriteLine(" --enable-opt NAME [ASM] Enable one of the additional optimizations globaly or for a specific assembly name");
13651369
Console.WriteLine(" sealer: Any method or type which does not have override is marked as sealed");
13661370
Console.WriteLine(" --explicit-reflection Adds to members never used through reflection DisablePrivateReflection attribute. Defaults to false");

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp