diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
index ba1e1480ed8e6f..967359e64cb15c 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
@@ -244,6 +244,7 @@ The .NET Foundation licenses this file to you under the MIT license.
+
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs
index 8d596f87e43f31..694a95620550d7 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Generic;
namespace ILCompiler
{
@@ -132,7 +133,7 @@ public CompilationBuilder UseDwarf5(bool value)
protected PreinitializationManager GetPreinitializationManager()
{
if (_preinitializationManager == null)
- return new PreinitializationManager(_context, _compilationGroup, GetILProvider(), new TypePreinit.DisabledPreinitializationPolicy(), new StaticReadOnlyFieldPolicy());
+ return new PreinitializationManager(_context, _compilationGroup, GetILProvider(), new TypePreinit.DisabledPreinitializationPolicy(), new StaticReadOnlyFieldPolicy(), new Dictionary());
return _preinitializationManager;
}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PreinitializationManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PreinitializationManager.cs
index 59aa509360464e..17494cd874f6dc 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PreinitializationManager.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PreinitializationManager.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Collections.Generic;
using System.Diagnostics;
using Internal.IL;
using Internal.TypeSystem;
@@ -14,10 +15,10 @@ public class PreinitializationManager
{
private readonly bool _supportsLazyCctors;
- public PreinitializationManager(TypeSystemContext context, CompilationModuleGroup compilationGroup, ILProvider ilprovider, TypePreinit.TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy)
+ public PreinitializationManager(TypeSystemContext context, CompilationModuleGroup compilationGroup, ILProvider ilprovider, TypePreinit.TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy, IReadOnlyDictionary featureSwitches)
{
_supportsLazyCctors = context.SystemModule.GetType("System.Runtime.CompilerServices", "ClassConstructorRunner", throwIfNotFound: false) != null;
- _preinitHashTable = new PreinitializationInfoHashtable(compilationGroup, ilprovider, policy, readOnlyPolicy);
+ _preinitHashTable = new PreinitializationInfoHashtable(compilationGroup, ilprovider, policy, readOnlyPolicy, featureSwitches);
}
///
@@ -137,13 +138,15 @@ private sealed class PreinitializationInfoHashtable : LockFreeReaderHashtable _featureSwitches;
- public PreinitializationInfoHashtable(CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinit.TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy)
+ public PreinitializationInfoHashtable(CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinit.TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy, IReadOnlyDictionary featureSwitches)
{
_compilationGroup = compilationGroup;
_ilProvider = ilProvider;
_policy = policy;
_readOnlyPolicy = readOnlyPolicy;
+ _featureSwitches = featureSwitches;
}
protected override bool CompareKeyToValue(MetadataType key, TypePreinit.PreinitializationInfo value) => key == value.Type;
@@ -153,7 +156,7 @@ public PreinitializationInfoHashtable(CompilationModuleGroup compilationGroup, I
protected override TypePreinit.PreinitializationInfo CreateValueFromKey(MetadataType key)
{
- var info = TypePreinit.ScanType(_compilationGroup, _ilProvider, _policy, _readOnlyPolicy, key);
+ var info = TypePreinit.ScanType(_compilationGroup, _ilProvider, _policy, _readOnlyPolicy, _featureSwitches, key);
// We either successfully preinitialized or
// the type doesn't have a canonical form or
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs
index 6f5fa941b6a1ca..c82b866f2c4c98 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs
@@ -39,14 +39,16 @@ public class TypePreinit
private readonly Dictionary _fieldValues = new Dictionary();
private readonly Dictionary _internedStrings = new Dictionary();
private readonly Dictionary _internedTypes = new Dictionary();
+ private readonly IReadOnlyDictionary _featureSwitches;
- private TypePreinit(MetadataType owningType, CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy)
+ private TypePreinit(MetadataType owningType, CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy, IReadOnlyDictionary featureSwitches)
{
_type = owningType;
_compilationGroup = compilationGroup;
_ilProvider = ilProvider;
_policy = policy;
_readOnlyPolicy = readOnlyPolicy;
+ _featureSwitches = featureSwitches;
// Zero initialize all fields we model.
foreach (var field in owningType.GetFields())
@@ -58,7 +60,7 @@ private TypePreinit(MetadataType owningType, CompilationModuleGroup compilationG
}
}
- public static PreinitializationInfo ScanType(CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy, MetadataType type)
+ public static PreinitializationInfo ScanType(CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy, IReadOnlyDictionary featureSwitches, MetadataType type)
{
Debug.Assert(type.HasStaticConstructor);
Debug.Assert(!type.IsGenericDefinition);
@@ -85,7 +87,7 @@ public static PreinitializationInfo ScanType(CompilationModuleGroup compilationG
Status status;
try
{
- preinit = new TypePreinit(type, compilationGroup, ilProvider, policy, readOnlyPolicy);
+ preinit = new TypePreinit(type, compilationGroup, ilProvider, policy, readOnlyPolicy, featureSwitches);
int instructions = 0;
status = preinit.TryScanMethod(type.GetStaticConstructor(), null, null, ref instructions, out _);
}
@@ -351,7 +353,7 @@ private Status TryScanMethod(MethodIL methodIL, Value[] parameters, Stack();
recursionProtect.Push(methodIL.OwningMethod);
@@ -466,7 +468,7 @@ private Status TryScanMethod(MethodIL methodIL, Value[] parameters, Stack();
recursionProtect.Push(methodIL.OwningMethod);
@@ -1886,6 +1888,16 @@ private bool TryHandleIntrinsicCall(MethodDesc method, Value[] parameters, out V
retVal = ValueTypeValue.FromSByte(parameters[0] == parameters[1] ? (sbyte)1 : (sbyte)0);
return true;
}
+ case "TryGetSwitch" when method.OwningType is MetadataType appContextType
+ && appContextType.Name == "AppContext" && appContextType.Namespace == "System"
+ && appContextType.Module == appContextType.Context.SystemModule
+ && parameters[0] is StringInstance switchName && parameters[1] is ByRefValue switchValueLocation
+ && _featureSwitches.TryGetValue(switchName.ValueAsString, out bool switchValue):
+ {
+ switchValueLocation.WriteAsBool(switchValue);
+ retVal = ValueTypeValue.FromSByte(1);
+ return true;
+ }
}
return false;
@@ -2623,11 +2635,11 @@ public override bool GetRawData(NodeFactory factory, out object data)
return false;
}
- private ReadOnlySpan AsExactByteCount(int count)
+ private Span AsExactByteCount(int count)
{
if (PointedToOffset + count > PointedToBytes.Length)
ThrowHelper.ThrowInvalidProgramException();
- return new ReadOnlySpan(PointedToBytes, PointedToOffset, count);
+ return new Span(PointedToBytes, PointedToOffset, count);
}
public sbyte DereferenceAsSByte() => (sbyte)AsExactByteCount(1)[0];
@@ -2636,6 +2648,7 @@ private ReadOnlySpan AsExactByteCount(int count)
public long DereferenceAsInt64() => BitConverter.ToInt64(AsExactByteCount(8));
public float DereferenceAsSingle() => BitConverter.ToSingle(AsExactByteCount(4));
public double DereferenceAsDouble() => BitConverter.ToDouble(AsExactByteCount(8));
+ public void WriteAsBool(bool value) => BitConverter.TryWriteBytes(AsExactByteCount(1), value);
}
private abstract class ReferenceTypeValue : Value
@@ -2904,7 +2917,7 @@ private sealed class StringInstance : ReferenceTypeValue, IHasInstanceFields
{
private readonly byte[] _value;
- private string ValueAsString
+ public string ValueAsString
{
get
{
diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs
index 66df76365d8d28..29dab15fb50e3b 100644
--- a/src/coreclr/tools/aot/ILCompiler/Program.cs
+++ b/src/coreclr/tools/aot/ILCompiler/Program.cs
@@ -436,7 +436,7 @@ public int Run()
TypePreinit.TypePreinitializationPolicy preinitPolicy = preinitStatics ?
new TypePreinit.TypeLoaderAwarePreinitializationPolicy() : new TypePreinit.DisabledPreinitializationPolicy();
- var preinitManager = new PreinitializationManager(typeSystemContext, compilationGroup, ilProvider, preinitPolicy, new StaticReadOnlyFieldPolicy());
+ var preinitManager = new PreinitializationManager(typeSystemContext, compilationGroup, ilProvider, preinitPolicy, new StaticReadOnlyFieldPolicy(), featureSwitches);
builder
.UseILProvider(ilProvider)
.UsePreinitializationManager(preinitManager);
@@ -515,7 +515,7 @@ void RunScanner()
{
var readOnlyFieldPolicy = scanResults.GetReadOnlyFieldPolicy();
preinitManager = new PreinitializationManager(typeSystemContext, compilationGroup, ilProvider, scanResults.GetPreinitializationPolicy(),
- readOnlyFieldPolicy);
+ readOnlyFieldPolicy, featureSwitches);
builder.UsePreinitializationManager(preinitManager)
.UseReadOnlyFieldPolicy(readOnlyFieldPolicy);
}
diff --git a/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj b/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj
index 752d76b2687c3c..59c74f6a222ea0 100644
--- a/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj
+++ b/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj
@@ -3,6 +3,8 @@
Exe
0
$(DefineConstants);RESOURCE_KEYS
+
+ true
true
@@ -10,10 +12,6 @@
true
-
-
-
-