diff options
author | Marek Safar <marek.safar@gmail.com> | 2019-10-26 09:20:15 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2019-12-11 02:05:36 +0300 |
commit | 132d8afe7ac5eae64b7597f120319fd2ccca5d5a (patch) | |
tree | 195bf01f9ee9602bb0833a941b436576bafbe6c9 /test/Mono.Linker.Tests.Cases | |
parent | b4770592e35a54823ef5705cc339bf6327229570 (diff) |
Add new optimization steps to make Mark step more effective
Two new steps have been introduced
BodySubstituterStep
This step removes any conditional blocks when the condition or conditions
are evaluated as constants. This step does not do any inlining. The conditional
logic is kept but based on the known values only one branch is always taken.
A simple example which can be detected by linker.
```c#
class C
{
static void Main ()
{
if (Result)
Console.WriteLine (); // <- this call will be marked and removed
}
static bool Result () => false;
}
```
RemoveUnreachableBlocksStep
A new command-line option called `--substitutions` allow external customization of any
methoda for assemblies which are linked. The syntax is same as for existing linker descriptor
XML files but it add way to control body modifications.
An example of XML file
```xml
<linker>
<assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<type fullname="Mono.Linker.Tests.Cases.Substitutions.StubBodyWithValue">
<method signature="System.String TestMethod_1()" body="stub" value="abcd">
</method>
</type>
</assembly>
</linker>
```
The `value` attribute is optional and only required when the method stub should not
fallback to default behaviour.
Additional to `stub` value also `remove` value is supported to forcibly remove body
of the method when the method is marked. This is useful when the conditional logic
cannot be evaluated by linker and the method will be marked but never actually reached.
Applicability
Both steps can be combined to achieve the effect of externally customizing which
conditional branches can be removed during the linking.
I can illustrate that on IntPtr.Size property. With following substitution any code
that has compiled in conditional logic for 64 bits handling by checking IntPtr.Size will
be removed during linking.
```xml
<linker>
<assembly fullname="mscorlib">
<type fullname="System.IntPtr">
<method signature="System.Int32 get_Size()" body="stub" value="4">
</method>
</type>
</assembly>
</linker>
```
Implements #752
Diffstat (limited to 'test/Mono.Linker.Tests.Cases')
17 files changed, 1001 insertions, 0 deletions
diff --git a/test/Mono.Linker.Tests.Cases/Substitutions/RemoveBody.cs b/test/Mono.Linker.Tests.Cases/Substitutions/RemoveBody.cs new file mode 100644 index 000000000..cd9f5285c --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Substitutions/RemoveBody.cs @@ -0,0 +1,65 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Substitutions +{ + [SetupLinkerSubstitutionFile ("RemoveBody.xml")] + public class RemoveBody + { + public static void Main () + { + new RemoveBody (); + new NestedType (5); + + TestMethod_1 (); + TestMethod_2<int> (); + } + + struct NestedType + { + [Kept] + [ExpectedInstructionSequence (new [] { + "ldstr", + "newobj", + "throw" + })] + public NestedType (int arg) + { + } + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldarg.0", + "call", + "ldstr", + "newobj", + "throw" + })] + public RemoveBody () + { + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldstr", + "newobj", + "throw" + })] + static void TestMethod_1 () + { + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldstr", + "newobj", + "throw" + })] + [ExpectLocalsModified] + static T TestMethod_2<T> () + { + return default (T); + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/Substitutions/RemoveBody.xml b/test/Mono.Linker.Tests.Cases/Substitutions/RemoveBody.xml new file mode 100644 index 000000000..cac95acfa --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Substitutions/RemoveBody.xml @@ -0,0 +1,17 @@ +<linker> + <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"> + <type fullname="Mono.Linker.Tests.Cases.Substitutions.RemoveBody"> + <method signature="System.Void TestMethod_1()" body="remove"> + </method> + <method signature="T TestMethod_2`1()" body="remove"> + </method> + <method signature="System.Void .ctor()" body="remove"> + </method> + </type> + + <type fullname="Mono.Linker.Tests.Cases.Substitutions.RemoveBody/NestedType"> + <method signature="System.Void .ctor(System.Int32)" body="remove"> + </method> + </type> + </assembly> +</linker> diff --git a/test/Mono.Linker.Tests.Cases/Substitutions/StubBody.cs b/test/Mono.Linker.Tests.Cases/Substitutions/StubBody.cs new file mode 100644 index 000000000..a685ed32b --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Substitutions/StubBody.cs @@ -0,0 +1,178 @@ +using System; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Substitutions { + [SetupLinkerSubstitutionFile ("StubBody.xml")] + public class StubBody { + public static void Main () + { + new StubBody (); + new NestedType (5); + + TestMethod_1 (); + TestMethod_2 (); + TestMethod_3 (); + TestMethod_4 (); + TestMethod_5 (); + TestMethod_6 (); + TestMethod_7 (); + TestMethod_8 (5); + TestMethod_9 (); + TestMethod_10 (); + TestMethod_11 (); + TestMethod_12 (); + } + + struct NestedType { + [Kept] + [ExpectedInstructionSequence (new [] { + "ret", + })] + public NestedType (int arg) + { + throw new NotImplementedException (); + } + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldarg.0", + "call", + "ret", + })] + public StubBody () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldnull", + "ret", + })] + static string TestMethod_1 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.i4.0", + "ret", + })] + static byte TestMethod_2 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.i4.0", + "ret", + })] + static char TestMethod_3 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldloca.s", + "initobj", + "ldloc.0", + "ret" + })] + [ExpectLocalsModified] + static decimal TestMethod_4 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.i4.0", + "ret", + })] + static bool TestMethod_5 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ret", + })] + static void TestMethod_6 () + { + TestMethod_5 (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.r8", + "ret", + })] + [ExpectLocalsModified] + static double TestMethod_7 () + { + double d = 1.1; + return d; + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldloca.s", + "initobj", + "ldloc.0", + "ret" + })] + [ExpectLocalsModified] + static T TestMethod_8<T> (T t) + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.r4", + "ret", + })] + [ExpectLocalsModified] + static float TestMethod_9 () + { + float f = 1.1f; + return f; + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.i8", + "ret", + })] + static ulong TestMethod_10 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldnull", + "ret", + })] + static long [] TestMethod_11 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldnull", + "ret", + })] + static object TestMethod_12 () + { + throw new NotImplementedException (); + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/Substitutions/StubBody.xml b/test/Mono.Linker.Tests.Cases/Substitutions/StubBody.xml new file mode 100644 index 000000000..dde512798 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Substitutions/StubBody.xml @@ -0,0 +1,38 @@ +<linker> + <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"> + <type fullname="Mono.Linker.Tests.Cases.Substitutions.StubBody"> + <method signature="System.String TestMethod_1()" body="stub"> + </method> + <method signature="System.Byte TestMethod_2()" body="stub"> + </method> + <method signature="System.Char TestMethod_3()" body="stub"> + </method> + <method signature="System.Decimal TestMethod_4()" body="stub"> + </method> + <method signature="System.Boolean TestMethod_5()" body="stub"> + </method> + <method signature="System.Void TestMethod_6()" body="stub"> + </method> + <method signature="System.Double TestMethod_7()" body="stub"> + </method> + <method signature="T TestMethod_8`1(T)" body="stub"> + </method> + <method signature="System.Single TestMethod_9()" body="stub"> + </method> + <method signature="System.UInt64 TestMethod_10()" body="stub"> + </method> + <method signature="System.Int64[] TestMethod_11()" body="stub"> + </method> + <method signature="System.Object TestMethod_12()" body="stub"> + </method> + + <method signature="System.Void .ctor()" body="stub"> + </method> + </type> + + <type fullname="Mono.Linker.Tests.Cases.Substitutions.StubBody/NestedType"> + <method signature="System.Void .ctor(System.Int32)" body="stub"> + </method> + </type> + </assembly> +</linker> diff --git a/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyInvalidSyntax.cs b/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyInvalidSyntax.cs new file mode 100644 index 000000000..a5c302d10 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyInvalidSyntax.cs @@ -0,0 +1,106 @@ +using System; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Substitutions +{ + [SetupLinkerSubstitutionFile ("StubBodyInvalidSyntax.xml")] + public class StubBodyInvalidSyntax + { + public static void Main() + { + new StubBodyInvalidSyntax (); + + TestMethod_1 (); + TestMethod_2 (); + TestMethod_3 (); + TestMethod_4 (); + TestMethod_5 (); + TestMethod_6 (); + TestMethod_7 (); + TestMethod_8 (5); + TestMethod_9 (); + TestMethod_10 (); + TestMethod_11 (); + TestMethod_12 (); + } + + [Kept] + public StubBodyInvalidSyntax() + { + throw new NotImplementedException (); + } + + [Kept] + static sbyte TestMethod_1 () + { + throw new NotImplementedException (); + } + + [Kept] + static byte TestMethod_2 () + { + return 3; + } + + [Kept] + static char TestMethod_3 () + { + return 'a'; + } + + [Kept] + static decimal TestMethod_4 () + { + return 9.2m; + } + + [Kept] + static bool TestMethod_5() + { + return true; + } + + [Kept] + static void TestMethod_6() + { + TestMethod_5 (); + } + + [Kept] + static double TestMethod_7() + { + throw new NotImplementedException (); + } + + [Kept] + static int TestMethod_8<T> (T t) + { + throw new NotImplementedException (); + } + + [Kept] + static float TestMethod_9() + { + throw new NotImplementedException (); + } + + [Kept] + static ulong TestMethod_10() + { + throw new NotImplementedException (); + } + + [Kept] + static long[] TestMethod_11() + { + throw new NotImplementedException (); + } + + [Kept] + static object TestMethod_12() + { + throw new NotImplementedException (); + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyInvalidSyntax.xml b/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyInvalidSyntax.xml new file mode 100644 index 000000000..332ed698a --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyInvalidSyntax.xml @@ -0,0 +1,32 @@ +<linker> + <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"> + <type fullname="Mono.Linker.Tests.Cases.Substitutions.StubBodyInvalidSyntax"> + <method signature="System.SByte TestMethod_1()" body="stub" value="200"> + </method> + <method signature="System.Byte TestMethod_2()" body="stub" value="300"> + </method> + <method signature="System.Char TestMethod_3()" body="stub" value="xy"> + </method> + <method signature="System.Decimal TestMethod_4()" body="stub" value="2"> + </method> + <method signature="System.Boolean TestMethod_5()" body="stub" value="test"> + </method> + <method signature="System.Void TestMethod_6()" body="stub" value="3"> + </method> + <method signature="System.Double TestMethod_7()" body="stub" value="text"> + </method> + <method signature="System.Int32 TestMethod_8`1(T)" body="stub" value="test"> + </method> + <method signature="System.Single TestMethod_9()" body="stub" value="test"> + </method> + <method signature="System.UInt64 TestMethod_10()" body="stub" value="test"> + </method> + <method signature="System.Int64[] TestMethod_11()" body="stub" value="1"> + </method> + <method signature="System.Object TestMethod_12()" body="stub" value="test"> + </method> + <method signature="System.Void .ctor()" body="stub" value="x">> + </method> + </type> + </assembly> +</linker> diff --git a/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyWithValue.cs b/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyWithValue.cs new file mode 100644 index 000000000..40ec1b7c4 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyWithValue.cs @@ -0,0 +1,124 @@ +using System; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Substitutions +{ + [SetupLinkerSubstitutionFile ("StubBodyWithValue.xml")] + public class StubBodyWithValue + { + public static void Main() + { + TestMethod_1 (); + TestMethod_2 (); + TestMethod_3 (); + TestMethod_4 (); + TestMethod_5 (); + TestMethod_6 (); + TestMethod_7 (); + TestMethod_8 (); + TestMethod_9 (); + TestMethod_10 (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldstr", + "ret", + })] + static string TestMethod_1 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.i4", + "ret", + })] + static byte TestMethod_2 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.i4", + "ret", + })] + static char TestMethod_3 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.i4", + "ret" + })] + static sbyte TestMethod_4 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.i4.1", + "ret", + })] + static bool TestMethod_5() + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.i4.1", + "ret", + })] + static bool TestMethod_6() + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.r8", + "ret", + })] + static double TestMethod_7() + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.i4", + "ret" + })] + static int TestMethod_8 () + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.r4", + "ret", + })] + static float TestMethod_9() + { + throw new NotImplementedException (); + } + + [Kept] + [ExpectedInstructionSequence (new [] { + "ldc.i8", + "ret", + })] + static ulong TestMethod_10() + { + throw new NotImplementedException (); + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyWithValue.xml b/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyWithValue.xml new file mode 100644 index 000000000..36191c79d --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyWithValue.xml @@ -0,0 +1,26 @@ +<linker> + <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"> + <type fullname="Mono.Linker.Tests.Cases.Substitutions.StubBodyWithValue"> + <method signature="System.String TestMethod_1()" body="stub" value="abcd"> + </method> + <method signature="System.Byte TestMethod_2()" body="stub" value="4"> + </method> + <method signature="System.Char TestMethod_3()" body="stub" value="x"> + </method> + <method signature="System.SByte TestMethod_4()" body="stub" value="3"> + </method> + <method signature="System.Boolean TestMethod_5()" body="stub" value="true"> + </method> + <method signature="System.Boolean TestMethod_6()" body="stub" value="1"> + </method> + <method signature="System.Double TestMethod_7()" body="stub" value="2.5"> + </method> + <method signature="System.Int32 TestMethod_8()" body="stub" value="-3"> + </method> + <method signature="System.Single TestMethod_9()" body="stub" value="6"> + </method> + <method signature="System.UInt64 TestMethod_10()" body="stub" value="123456"> + </method> + </type> + </assembly> +</linker> diff --git a/test/Mono.Linker.Tests.Cases/UnreachableBlock/BodiesWithSubstitutions.cs b/test/Mono.Linker.Tests.Cases/UnreachableBlock/BodiesWithSubstitutions.cs new file mode 100644 index 000000000..0dd3e9c26 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/BodiesWithSubstitutions.cs @@ -0,0 +1,39 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.UnreachableBlock +{ + [SetupLinkerSubstitutionFile ("BodiesWithSubstitutions.xml")] + [SetupCSharpCompilerToUse ("csc")] + public class BodiesWithSubstitutions + { + static int field; + + public static void Main() + { + TestProperty_int_1 (); + } + + [Kept] + [ExpectBodyModified] + static void TestProperty_int_1 () + { + if (Property != 3) + NeverReached_1 (); + } + + [Kept] + static int Property { + [Kept] + [ExpectBodyModified] + [ExpectLocalsModified] + get { + return field; + } + } + + static void NeverReached_1 () + { + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/UnreachableBlock/BodiesWithSubstitutions.xml b/test/Mono.Linker.Tests.Cases/UnreachableBlock/BodiesWithSubstitutions.xml new file mode 100644 index 000000000..c34957411 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/BodiesWithSubstitutions.xml @@ -0,0 +1,8 @@ +<linker> + <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"> + <type fullname="Mono.Linker.Tests.Cases.UnreachableBlock.BodiesWithSubstitutions"> + <method signature="System.Int32 get_Property()" body="stub" value="3"> + </method> + </type> + </assembly> +</linker> diff --git a/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs b/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs new file mode 100644 index 000000000..9a92ab742 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs @@ -0,0 +1,35 @@ +using System; +using System.Reflection.Emit; +using Mono.Linker.Tests.Cases.Expectations.Assertions; + +namespace Mono.Linker.Tests.Cases.UnreachableBlock +{ + public class ComplexConditions + { + public static void Main() + { + Test_1 (null); + } + + [Kept] + [ExpectBodyModified] + static void Test_1 (object type) + { + if (type is Type || (IsDynamicCodeSupported && type is TypeBuilder)) + Reached_1 (); + } + + [Kept] + static bool IsDynamicCodeSupported { + [Kept] + get { + return true; + } + } + + [Kept] + static void Reached_1 () + { + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/UnreachableBlock/MultiStageRemoval.cs b/test/Mono.Linker.Tests.Cases/UnreachableBlock/MultiStageRemoval.cs new file mode 100644 index 000000000..9ef8c1f01 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/MultiStageRemoval.cs @@ -0,0 +1,79 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.UnreachableBlock +{ + public class MultiStageRemoval + { + public static void Main() + { + TestMethod_1 (); + TestMethod_2 (); + } + + [Kept] + [ExpectBodyModified] + static void TestMethod_1 () + { + if (TestProperty_int () == 0) + NeverReached_1 (); + } + + [Kept] + [ExpectBodyModified] + static void TestMethod_2 () + { + if (TestProperty_bool_twice () >= 0) + NeverReached_2 (); + } + + [Kept] + [ExpectBodyModified] + static int TestProperty_int () + { + if (Prop > 5) { + return 11; + } + + return 0; + } + + [Kept] + [ExpectBodyModified] + static int TestProperty_bool_twice () + { + if (PropBool) { + return -5; + } + + if (TestProperty_bool_twice () == 4) + return -1; + + return 0; + } + + [Kept] + static int Prop { + [Kept] + get { + return 9; + } + } + + [Kept] + static bool PropBool { + [Kept] + get { + return true; + } + } + + static void NeverReached_1 () + { + } + + static void NeverReached_2 () + { + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/UnreachableBlock/SimpleConditionalProperty.cs b/test/Mono.Linker.Tests.Cases/UnreachableBlock/SimpleConditionalProperty.cs new file mode 100644 index 000000000..f95a67a14 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/SimpleConditionalProperty.cs @@ -0,0 +1,147 @@ +using System; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.UnreachableBlock +{ +// [SetupCSharpCompilerToUse ("csc")] + public class SimpleConditionalProperty + { + public static void Main() + { + TestProperty_int_1 (); + TestProperty_int_2 (); + TestProperty_int_3 (); + TestProperty_bool_1 (); + TestProperty_bool_2 (); + TestProperty_bool_3 (); + TestProperty_enum_1 (); + TestProperty_null_1 (); + } + + [Kept] + [ExpectBodyModified] + static void TestProperty_int_1 () + { + if (Prop != 3) + NeverReached_1 (); + } + + [Kept] + [ExpectBodyModified] + static void TestProperty_int_2 () + { + if (3 == Prop) { + + } else { + NeverReached_1 (); + } + } + + [Kept] + [ExpectBodyModified] + static int TestProperty_int_3 () + { + if (Prop > 5 && TestProperty_int_3 () == 0) { + NeverReached_1 (); + } + + return 0; + } + + [Kept] + [ExpectBodyModified] + static void TestProperty_bool_1 () + { + if (!PropBool) { + + } else { + NeverReached_1 (); + } + } + + [Kept] + [ExpectBodyModified] + static void TestProperty_bool_2 () + { + if (PropBool) { + NeverReached_1 (); + } + } + + [Kept] + [ExpectBodyModified] + static void TestProperty_bool_3 () + { + if (PropBool != PropBool) { + NeverReached_1 (); + } + } + + [Kept] + [ExpectBodyModified] + static void TestProperty_enum_1 () + { + while (PropEnum == TestEnum.C) { + NeverReached_1 (); + } + } + + [Kept] + [ExpectBodyModified] + static void TestProperty_null_1 () + { + if (PropNull != null) + NeverReached_1 (); + } + + [Kept] + static int Prop { + [Kept] + get { + int i = 3; + return i; + } + } + + [Kept] + static bool PropBool { + [Kept] + get { + return false; + } + } + + [Kept] + static TestEnum PropEnum { + [Kept] + get { + return TestEnum.B; + } + } + + [Kept] + static string PropNull { + [Kept] + get { + return null; + } + } + + static void NeverReached_1 () + { + } + + [Kept] + [KeptMember ("value__")] + [KeptBaseType (typeof (Enum))] + enum TestEnum { + [Kept] + A = 0, + [Kept] + B = 1, + [Kept] + C = 2 + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.cs b/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.cs new file mode 100644 index 000000000..5bc7bbe90 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.cs @@ -0,0 +1,47 @@ +using System; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.UnreachableBlock { +#if ILLINK + [SetupLinkerSubstitutionFile ("SizeOfInConditions.netcore.xml")] +#else + [SetupLinkerSubstitutionFile ("SizeOfInConditions.net_4_x.xml")] +#endif + [SetupCompileArgument ("/unsafe")] + public unsafe class SizeOfInConditions { + public static void Main () + { + TestIntPtr (); + TestUIntPtr (); + } + + [Kept] + [ExpectBodyModified] + static void TestIntPtr () + { + if (sizeof (IntPtr) != 4) { + } else { + Reached_1 (); + } + } + + [Kept] + [ExpectBodyModified] + static void TestUIntPtr () + { + if (sizeof (UIntPtr) != 8) { + } else { + Reached_2 (); + } + } + + static void Reached_1 () + { + } + + static void Reached_2 () + { + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.net_4_x.xml b/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.net_4_x.xml new file mode 100644 index 000000000..bff4c3b81 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.net_4_x.xml @@ -0,0 +1,12 @@ +<linker> + <assembly fullname="mscorlib"> + <type fullname="System.IntPtr"> + <method signature="System.Int32 get_Size()" body="stub" value="16"> + </method> + </type> + <type fullname="System.UIntPtr"> + <method signature="System.Int32 get_Size()" body="stub" value="32"> + </method> + </type> + </assembly> +</linker> diff --git a/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.netcore.xml b/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.netcore.xml new file mode 100644 index 000000000..5b53cc7b8 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.netcore.xml @@ -0,0 +1,12 @@ +<linker> + <assembly fullname="System.Private.CoreLib"> + <type fullname="System.IntPtr"> + <method signature="System.Int32 get_Size()" body="stub" value="16"> + </method> + </type> + <type fullname="System.UIntPtr"> + <method signature="System.Int32 get_Size()" body="stub" value="32"> + </method> + </type> + </assembly> +</linker> diff --git a/test/Mono.Linker.Tests.Cases/UnreachableBlock/TryFinallyBlocks.cs b/test/Mono.Linker.Tests.Cases/UnreachableBlock/TryFinallyBlocks.cs new file mode 100644 index 000000000..defc213d4 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/TryFinallyBlocks.cs @@ -0,0 +1,36 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; + +namespace Mono.Linker.Tests.Cases.UnreachableBlock +{ + public class TryFinallyBlocks + { + public static void Main () + { + TestSimpleTry (); + } + + [Kept] + static void TestSimpleTry () + { + if (Prop != 3) + Reached_1 (); + } + + [Kept] + static int Prop { + [Kept] + get { + try { + return 3; + } finally { + + } + } + } + + [Kept] + static void Reached_1 () + { + } + } +}
\ No newline at end of file |