Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.IO;
using System.Reflection.Metadata;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
using System.Xml;
using System.Xml.XPath;
using System.Globalization;
Expand Down Expand Up @@ -163,6 +164,26 @@ private static MethodDesc FindMethod(TypeDesc type, string signature)

private static object TryCreateSubstitution(TypeDesc type, string value)
{
if (type.IsEnum && type.UnderlyingType.Category == TypeFlags.Int32)
{
foreach (FieldDesc field in type.GetFields())
{
if (field.IsStatic &&
field.Name.StringEquals(value) &&
field is EcmaField ecmaField)
{
MetadataReader reader = ecmaField.MetadataReader;
ConstantHandle constantHandle = reader.GetFieldDefinition(ecmaField.Handle).GetDefaultValue();
if (!constantHandle.IsNil)
{
Constant constant = reader.GetConstant(constantHandle);
if (constant.TypeCode == ConstantTypeCode.Int32)
return reader.GetBlobReader(constant.Value).ReadInt32();
}
}
}
}

switch (type.UnderlyingType.Category)
{
case TypeFlags.Int32:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public void Substitutions(string t)
{
switch (t)
{
case "EnumSubstitutions":
case "FeatureGuardSubstitutions":
Run(t);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,10 @@ public bool TryConvertValue(string value, TypeReference target, out object? resu
result = Convert.ToInt32(enumField.Constant);
return true;
}

var underlyingType = typeDefinition.GetEnumUnderlyingType();
if (underlyingType.MetadataType == MetadataType.Int32)
return TryConvertValue(value, underlyingType, out result);
}

break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Runtime.CompilerServices;
using Mono.Linker.Tests.Cases.Expectations.Assertions;
using Mono.Linker.Tests.Cases.Expectations.Metadata;

namespace Mono.Linker.Tests.Cases.Substitutions
{
[ExpectedNoWarnings]
[SetupLinkerSubstitutionFile("EnumSubstitutions.xml")]
[IgnoreSubstitutions(false)]
[SkipKeptItemsValidation(By = Tool.NativeAot)]
public class EnumSubstitutions
{
[Kept]
[KeptMember("value__")]
[KeptBaseType(typeof(Enum))]
private enum SubstitutionValue
{
[Kept]
Initial,

[Kept]
ByName,

[Kept]
ByNumber,
}

[Kept]
private static readonly SubstitutionValue FieldByName = SubstitutionValue.Initial;

[Kept]
private static readonly SubstitutionValue FieldByNumber = SubstitutionValue.Initial;

public static void Main()
{
VerifyFieldByNameSubstitution();
VerifyFieldByNumberSubstitution();
MethodByName();
MethodByNumber();
}

[Kept]
[ExpectedInstructionSequence(new[] {
"nop",
"ldsfld Mono.Linker.Tests.Cases.Substitutions.EnumSubstitutions/SubstitutionValue Mono.Linker.Tests.Cases.Substitutions.EnumSubstitutions::FieldByName",
"ldc.i4.1",
"ceq",
"ldc.i4.0",
"ceq",
"stloc.0",
"ldloc.0",
"brfalse.s il_10",
"ret",
})]
private static void VerifyFieldByNameSubstitution()
{
if (FieldByName != SubstitutionValue.ByName)
ReachableOnUnexpectedFieldByNameValue();
}

private static void ReachableOnUnexpectedFieldByNameValue()
{
}

[Kept]
[ExpectedInstructionSequence(new[] {
"nop",
"ldsfld Mono.Linker.Tests.Cases.Substitutions.EnumSubstitutions/SubstitutionValue Mono.Linker.Tests.Cases.Substitutions.EnumSubstitutions::FieldByNumber",
"ldc.i4.2",
"ceq",
"ldc.i4.0",
"ceq",
"stloc.0",
"ldloc.0",
"brfalse.s il_10",
"ret",
})]
private static void VerifyFieldByNumberSubstitution()
{
if (FieldByNumber != SubstitutionValue.ByNumber)
ReachableOnUnexpectedFieldByNumberValue();
}

private static void ReachableOnUnexpectedFieldByNumberValue()
{
}

[Kept]
[ExpectedInstructionSequence(new[] {
"ldc.i4 0x1",
"ret",
})]
[ExpectedLocalsSequence(new string[0])]
[MethodImpl(MethodImplOptions.NoInlining)]
private static SubstitutionValue MethodByName()
{
return SubstitutionValue.Initial;
}

[Kept]
[ExpectedInstructionSequence(new[] {
"ldc.i4 0x2",
"ret",
})]
[ExpectedLocalsSequence(new string[0])]
[MethodImpl(MethodImplOptions.NoInlining)]
private static SubstitutionValue MethodByNumber()
{
return SubstitutionValue.Initial;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<linker>
<assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<type fullname="Mono.Linker.Tests.Cases.Substitutions.EnumSubstitutions">
<field name="FieldByName" value="ByName" />
<field name="FieldByNumber" value="2" />
<method signature="Mono.Linker.Tests.Cases.Substitutions.EnumSubstitutions/SubstitutionValue MethodByName()" body="stub" value="ByName" />
<method signature="Mono.Linker.Tests.Cases.Substitutions.EnumSubstitutions/SubstitutionValue MethodByNumber()" body="stub" value="2" />
</type>
</assembly>
</linker>
Loading