Skip to content

Commit b2b6b84

Browse files
authored
Remove ILLink support for field init substitutions (#107380)
The implementation of this was attempting to rewrite the cctor in a way that was not robust.
1 parent 40063f8 commit b2b6b84

File tree

19 files changed

+19
-290
lines changed

19 files changed

+19
-290
lines changed

docs/tools/illink/data-formats.md

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -253,20 +253,6 @@ Entire method body is replaces with `throw` instruction when method is reference
253253
</linker>
254254
```
255255

256-
### Override static field value with a constant
257-
258-
The `initialize` attribute is optional and when not specified the code to set the static field to the value will not be generated.
259-
260-
```xml
261-
<linker>
262-
<assembly fullname="Assembly">
263-
<type fullname="Assembly.A">
264-
<field name="MyNumericField" value="5" initialize="true" />
265-
</type>
266-
</assembly>
267-
</linker>
268-
```
269-
270256
### Remove embedded resources
271257

272258
```xml

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,8 @@ protected override void ProcessField(TypeDesc type, XPathNavigator fieldNav)
144144

145145
if (string.Equals(GetAttribute(fieldNav, "initialize"), "true", StringComparison.InvariantCultureIgnoreCase))
146146
{
147-
// We would need to also mess with the cctor of the type to set the field to this value:
148-
//
149-
// * ILLink will remove all stsfld instructions referencing this field from the cctor
150-
// * It will place an explicit stsfld in front of the last "ret" instruction in the cctor
151-
//
152-
// This approach... has issues.
147+
// We would need to also mess with the cctor of the type to set the field to this value,
148+
// and doing so correctly is difficult.
153149
throw new NotSupportedException();
154150
}
155151

src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.Shared.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<method signature="System.Boolean InitializeBinaryFormatter()" body="stub" value="false" feature="System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization" featurevalue="false" />
2121
</type>
2222
<type fullname="System.Threading.Tasks.Task" feature="System.Diagnostics.Debugger.IsSupported" featurevalue="false">
23-
<field name="s_asyncDebuggingEnabled" value="false" initialize="false" />
23+
<field name="s_asyncDebuggingEnabled" value="false" />
2424
</type>
2525
</assembly>
2626
</linker>

src/tools/illink/src/linker/CompatibilitySuppressions.xml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -745,14 +745,6 @@
745745
<DiagnosticId>CP0002</DiagnosticId>
746746
<Target>M:Mono.Linker.AnnotationStore.HasPreservedStaticCtor(Mono.Cecil.TypeDefinition)</Target>
747747
</Suppression>
748-
<Suppression>
749-
<DiagnosticId>CP0002</DiagnosticId>
750-
<Target>M:Mono.Linker.AnnotationStore.HasSubstitutedInit(Mono.Cecil.FieldDefinition)</Target>
751-
</Suppression>
752-
<Suppression>
753-
<DiagnosticId>CP0002</DiagnosticId>
754-
<Target>M:Mono.Linker.AnnotationStore.HasSubstitutedInit(Mono.Cecil.TypeDefinition)</Target>
755-
</Suppression>
756748
<Suppression>
757749
<DiagnosticId>CP0002</DiagnosticId>
758750
<Target>M:Mono.Linker.AnnotationStore.IsIndirectlyCalled(Mono.Cecil.MethodDefinition)</Target>

src/tools/illink/src/linker/Linker.Steps/BodySubstitutionParser.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ protected override void ProcessField (TypeDefinition type, XPathNavigator fieldN
117117

118118
string init = GetAttribute (fieldNav, "initialize");
119119
if (init?.ToLowerInvariant () == "true") {
120-
_substitutionInfo.SetFieldInit (field);
120+
// We would need to also mess with the cctor of the type to set the field to this value,
121+
// and doing so correctly is difficult.
122+
throw new NotSupportedException ();
121123
}
122124
}
123125

src/tools/illink/src/linker/Linker.Steps/CodeRewriterStep.cs

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -37,68 +37,10 @@ void ProcessType (TypeDefinition type)
3737
ProcessMethod (method);
3838
}
3939

40-
if (type.HasFields && Annotations.HasSubstitutedInit (type)) {
41-
AddFieldsInitializations (type);
42-
}
43-
4440
foreach (var nested in type.NestedTypes)
4541
ProcessType (nested);
4642
}
4743

48-
void AddFieldsInitializations (TypeDefinition type)
49-
{
50-
Instruction ret;
51-
LinkerILProcessor processor;
52-
53-
var cctor = type.Methods.FirstOrDefault (MethodDefinitionExtensions.IsStaticConstructor);
54-
if (cctor == null) {
55-
type.Attributes |= TypeAttributes.BeforeFieldInit;
56-
57-
var method = new MethodDefinition (".cctor",
58-
MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
59-
Assembly.MainModule.TypeSystem.Void);
60-
61-
type.Methods.Add (method);
62-
63-
processor = method.Body.GetLinkerILProcessor ();
64-
ret = Instruction.Create (OpCodes.Ret);
65-
processor.Append (ret);
66-
} else {
67-
var body = cctor.Body;
68-
#pragma warning disable RS0030 // After MarkStep all methods should be processed and thus accessing Cecil directly is the right approach
69-
var instructions = body.Instructions;
70-
#pragma warning restore RS0030
71-
ret = instructions.Last (l => l.OpCode.Code == Code.Ret);
72-
processor = body.GetLinkerILProcessor ();
73-
74-
for (int i = 0; i < instructions.Count; ++i) {
75-
var instr = instructions[i];
76-
if (instr.OpCode.Code != Code.Stsfld)
77-
continue;
78-
79-
var field = (FieldReference) instr.Operand;
80-
if (!Annotations.HasSubstitutedInit (field.Resolve ()))
81-
continue;
82-
83-
processor.Replace (instr, Instruction.Create (OpCodes.Pop));
84-
}
85-
}
86-
87-
foreach (var field in type.Fields) {
88-
if (!Annotations.HasSubstitutedInit (field))
89-
continue;
90-
91-
Context.Annotations.TryGetFieldUserValue (field, out object? value);
92-
93-
var valueInstr = CreateConstantResultInstruction (Context, field.FieldType, value);
94-
if (valueInstr == null)
95-
throw new NotImplementedException (field.FieldType.ToString ());
96-
97-
processor.InsertBefore (ret, valueInstr);
98-
processor.InsertBefore (ret, Instruction.Create (OpCodes.Stsfld, field));
99-
}
100-
}
101-
10244
void ProcessMethod (MethodDefinition method)
10345
{
10446
switch (Annotations.GetAction (method)) {

src/tools/illink/src/linker/Linker.Steps/MarkStep.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,11 +1712,6 @@ void MarkField (FieldDefinition field, in DependencyInfo reason, in MessageOrigi
17121712
};
17131713
MarkStaticConstructor (parent, cctorReason, fieldOrigin);
17141714
}
1715-
1716-
if (Annotations.HasSubstitutedInit (field)) {
1717-
Annotations.SetPreservedStaticCtor (parent);
1718-
Annotations.SetSubstitutedInit (parent);
1719-
}
17201715
}
17211716

17221717
void ProcessAnalysisAnnotationsForField (FieldDefinition field, DependencyKind dependencyKind, in MessageOrigin origin)

src/tools/illink/src/linker/Linker/Annotations.cs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -147,21 +147,6 @@ public void SetStubValue (MethodDefinition method, object value)
147147
MemberActions.PrimarySubstitutionInfo.SetMethodStubValue (method, value);
148148
}
149149

150-
public bool HasSubstitutedInit (FieldDefinition field)
151-
{
152-
return MemberActions.HasSubstitutedInit (field);
153-
}
154-
155-
public void SetSubstitutedInit (TypeDefinition type)
156-
{
157-
fieldType_init.Add (type);
158-
}
159-
160-
public bool HasSubstitutedInit (TypeDefinition type)
161-
{
162-
return fieldType_init.Contains (type);
163-
}
164-
165150
[Obsolete ("Mark token providers with a reason instead.")]
166151
public void Mark (IMetadataTokenProvider provider)
167152
{

src/tools/illink/src/linker/Linker/MemberActionStore.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,16 +150,5 @@ public bool TryGetFieldUserValue (FieldDefinition field, out object? value)
150150

151151
return embeddedXml.FieldValues.TryGetValue (field, out value);
152152
}
153-
154-
public bool HasSubstitutedInit (FieldDefinition field)
155-
{
156-
if (PrimarySubstitutionInfo.FieldInit.Contains (field))
157-
return true;
158-
159-
if (!TryGetSubstitutionInfo (field, out var embeddedXml))
160-
return false;
161-
162-
return embeddedXml.FieldInit.Contains (field);
163-
}
164153
}
165154
}

src/tools/illink/src/linker/Linker/SubstitutionInfo.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@ public class SubstitutionInfo
1111
public Dictionary<MethodDefinition, MethodAction> MethodActions { get; }
1212
public Dictionary<MethodDefinition, object?> MethodStubValues { get; }
1313
public Dictionary<FieldDefinition, object?> FieldValues { get; }
14-
public HashSet<FieldDefinition> FieldInit { get; }
1514

1615
public SubstitutionInfo ()
1716
{
1817
MethodActions = new Dictionary<MethodDefinition, MethodAction> ();
1918
MethodStubValues = new Dictionary<MethodDefinition, object?> ();
2019
FieldValues = new Dictionary<FieldDefinition, object?> ();
21-
FieldInit = new HashSet<FieldDefinition> ();
2220
}
2321

2422
public void SetMethodAction (MethodDefinition method, MethodAction action)
@@ -35,10 +33,5 @@ public void SetFieldValue (FieldDefinition field, object? value)
3533
{
3634
FieldValues[field] = value;
3735
}
38-
39-
public void SetFieldInit (FieldDefinition field)
40-
{
41-
FieldInit.Add (field);
42-
}
4336
}
4437
}

0 commit comments

Comments
 (0)