Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/linker/Linker.Steps/RemoveUnreachableBlocksStep.cs43
-rw-r--r--test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs73
-rw-r--r--test/Mono.Linker.Tests.Cases/UnreachableBlock/SimpleConditionalProperty.cs1
3 files changed, 115 insertions, 2 deletions
diff --git a/src/linker/Linker.Steps/RemoveUnreachableBlocksStep.cs b/src/linker/Linker.Steps/RemoveUnreachableBlocksStep.cs
index 7aaa19a18..188389fee 100644
--- a/src/linker/Linker.Steps/RemoveUnreachableBlocksStep.cs
+++ b/src/linker/Linker.Steps/RemoveUnreachableBlocksStep.cs
@@ -339,6 +339,9 @@ namespace Mono.Linker.Steps
continue;
if (left is int lint && right is int rint) {
+ if (IsJumpTargetRange (i - 1, i))
+ continue;
+
RewriteToNop (i - 2);
RewriteToNop (i - 1);
@@ -358,6 +361,9 @@ namespace Mono.Linker.Steps
if (opcode.StackBehaviourPop == StackBehaviour.Popi) {
if (i > 0 && GetConstantValue (FoldedInstructions [i - 1], out var operand)) {
if (operand is int opint) {
+ if (IsJumpTargetRange (i, i))
+ continue;
+
RewriteToNop (i - 1);
if (IsConstantBranch (opcode, opint)) {
@@ -371,6 +377,9 @@ namespace Mono.Linker.Steps
}
if (operand is null && (opcode.Code == Code.Brfalse || opcode.Code == Code.Brfalse_S)) {
+ if (IsJumpTargetRange (i, i))
+ continue;
+
RewriteToNop (i - 1);
Rewrite (i, Instruction.Create (OpCodes.Br, (Instruction)instr.Operand));
changed = true;
@@ -380,6 +389,9 @@ namespace Mono.Linker.Steps
// Common pattern generated by C# compiler in debug mode
if (i > 3 && GetConstantValue (FoldedInstructions [i - 3], out operand) && operand is int opint2 && IsPairedStlocLdloc (FoldedInstructions [i - 2], FoldedInstructions [i - 1])) {
+ if (IsJumpTargetRange (i - 2, i))
+ continue;
+
RewriteToNop (i - 3);
RewriteToNop (i - 2);
RewriteToNop (i - 1);
@@ -409,6 +421,9 @@ namespace Mono.Linker.Steps
continue;
if (left is int lint && right is int rint) {
+ if (IsJumpTargetRange (i - 1, i))
+ continue;
+
RewriteToNop (i - 2);
RewriteToNop (i - 1);
@@ -427,6 +442,9 @@ namespace Mono.Linker.Steps
if (!GetOperandsConstantValues (i, out left, out right))
continue;
+ if (IsJumpTargetRange (i - 1, i))
+ continue;
+
if (left == null && right == null) {
Rewrite (i, Instruction.Create (OpCodes.Ldc_I4_0));
}
@@ -689,6 +707,31 @@ namespace Mono.Linker.Steps
throw new NotImplementedException (opCode.ToString ());
}
+
+ bool IsJumpTargetRange (int firstInstr, int lastInstr)
+ {
+ foreach (var instr in FoldedInstructions) {
+ switch (instr.OpCode.FlowControl) {
+ case FlowControl.Branch:
+ case FlowControl.Cond_Branch:
+ if (instr.Operand is Instruction target) {
+ var index = GetInstructionIndex (target);
+ if (index >= firstInstr && index <= lastInstr)
+ return true;
+ } else {
+ foreach (var rtarget in (Instruction [])instr.Operand) {
+ var index = GetInstructionIndex (rtarget);
+ if (index >= firstInstr && index <= lastInstr)
+ return true;
+ }
+ }
+
+ break;
+ }
+ }
+
+ return false;
+ }
}
struct BodySweeper
diff --git a/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs b/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs
index 9a92ab742..2660b240d 100644
--- a/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs
+++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs
@@ -1,18 +1,46 @@
using System;
using System.Reflection.Emit;
using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
namespace Mono.Linker.Tests.Cases.UnreachableBlock
{
+ [SetupCompileArgument ("/optimize-")] // Relying on debug csc behaviour
public class ComplexConditions
{
- public static void Main()
+ public static void Main ()
{
Test_1 (null);
+ Test_2 (9);
}
[Kept]
+#if !NETCOREAPP
[ExpectBodyModified]
+#else
+ [ExpectedInstructionSequence (new [] {
+ "nop",
+ "ldarg.0",
+ "isinst",
+ "brtrue.s",
+ "call",
+ "pop",
+ "ldarg.0",
+ "isinst",
+ "ldnull",
+ "cgt.un",
+ "br.s",
+ "nop",
+ "br.s",
+ "ldc.i4.1",
+ "stloc.0",
+ "ldloc.0",
+ "brfalse.s",
+ "call",
+ "nop",
+ "ret"
+ })]
+#endif
static void Test_1 (object type)
{
if (type is Type || (IsDynamicCodeSupported && type is TypeBuilder))
@@ -20,6 +48,47 @@ namespace Mono.Linker.Tests.Cases.UnreachableBlock
}
[Kept]
+#if !NETCOREAPP
+ [ExpectBodyModified]
+#else
+ [ExpectedInstructionSequence (new [] {
+ "nop",
+ "call",
+ "stloc.1",
+ "ldloc.1",
+ "pop",
+ "ldc.i4.0",
+ "stloc.0",
+ "ldarg.0",
+ "ldc.i4.2",
+ "beq.s",
+ "ldarg.0",
+ "ldc.i4.3",
+ "ceq",
+ "br.s",
+ "ldc.i4.1",
+ "stloc.2",
+ "ldloc.2",
+ "brfalse.s",
+ "newobj",
+ "throw",
+ "newobj",
+ "throw"
+ })]
+#endif
+ static void Test_2 (int a)
+ {
+ int zero;
+ if (IsDynamicCodeSupported)
+ zero = 0;
+
+ if (a == 2 || a == 3)
+ throw new ArgumentException ();
+
+ throw new ApplicationException ();
+ }
+
+ [Kept]
static bool IsDynamicCodeSupported {
[Kept]
get {
@@ -29,7 +98,7 @@ namespace Mono.Linker.Tests.Cases.UnreachableBlock
[Kept]
static void Reached_1 ()
- {
+ {
}
}
} \ 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
index f95a67a14..1b0eaad0d 100644
--- a/test/Mono.Linker.Tests.Cases/UnreachableBlock/SimpleConditionalProperty.cs
+++ b/test/Mono.Linker.Tests.Cases/UnreachableBlock/SimpleConditionalProperty.cs
@@ -5,6 +5,7 @@ using Mono.Linker.Tests.Cases.Expectations.Metadata;
namespace Mono.Linker.Tests.Cases.UnreachableBlock
{
// [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileArgument ("/optimize+")]
public class SimpleConditionalProperty
{
public static void Main()