Skip to content

Commit 1758547

Browse files
Merge pull request #3015 from ElektroKill/mcs264-pinned-region
2 parents 19e69e6 + 4601481 commit 1758547

File tree

4 files changed

+134
-18
lines changed

4 files changed

+134
-18
lines changed

ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
2-
//
2+
//
33
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
44
// software and associated documentation files (the "Software"), to deal in the Software
55
// without restriction, including without limitation the rights to use, copy, modify, merge,
66
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
77
// to whom the Software is furnished to do so, subject to the following conditions:
8-
//
8+
//
99
// The above copyright notice and this permission notice shall be included in all copies or
1010
// substantial portions of the Software.
11-
//
11+
//
1212
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
1313
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
1414
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
@@ -269,6 +269,12 @@ public async Task EmptyBodies()
269269
await Run();
270270
}
271271

272+
[Test]
273+
public async Task MonoFixed()
274+
{
275+
await Run();
276+
}
277+
272278
async Task Run([CallerMemberName] string testName = null, DecompilerSettings settings = null,
273279
AssemblerOptions assemblerOptions = AssemblerOptions.Library)
274280
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
3+
public class MonoFixed
4+
{
5+
public unsafe void FixMultipleStrings(string text)
6+
{
7+
fixed (char* ptr = text)
8+
{
9+
fixed (char* ptr2 = Environment.UserName)
10+
{
11+
fixed (char* ptr3 = text)
12+
{
13+
*ptr = 'c';
14+
*ptr2 = 'd';
15+
*ptr3 = 'e';
16+
}
17+
}
18+
}
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
.assembly extern mscorlib
2+
{
3+
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
4+
.ver 4:0:0:0
5+
}
6+
.assembly MonoFixed
7+
{
8+
.ver 1:0:0:0
9+
}
10+
11+
.module MonoFixed.exe
12+
.imagebase 0x00400000
13+
.file alignment 0x00000200
14+
.stackreserve 0x00100000
15+
.subsystem 0x0003 // WindowsCui
16+
.corflags 0x00000001 // ILOnly
17+
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = (
18+
01 00 00 00
19+
)
20+
21+
.class public auto ansi beforefieldinit MonoFixed
22+
extends [mscorlib]System.Object
23+
{
24+
.method public hidebysig instance void FixMultipleStrings (string text) cil managed
25+
{
26+
.maxstack 7
27+
.locals init (
28+
[0] char* pinned,
29+
[1] char* pinned,
30+
[2] char* pinned,
31+
[3] string pinned,
32+
[4] string pinned,
33+
[5] string pinned
34+
)
35+
36+
IL_0000: ldarg.1
37+
IL_0001: stloc.3
38+
IL_0002: ldloc.3
39+
IL_0003: conv.i
40+
IL_0004: call int32 [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData()
41+
IL_0009: add
42+
IL_000a: stloc.0
43+
IL_000b: call string [mscorlib]System.Environment::get_UserName()
44+
IL_0010: stloc.s 4
45+
IL_0012: ldloc.s 4
46+
IL_0014: conv.i
47+
IL_0015: call int32 [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData()
48+
IL_001a: add
49+
IL_001b: stloc.1
50+
IL_001c: ldarg.1
51+
IL_001d: stloc.s 5
52+
IL_001f: ldloc.s 5
53+
IL_0021: conv.i
54+
IL_0022: call int32 [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData()
55+
IL_0027: add
56+
IL_0028: stloc.2
57+
IL_0029: ldloc.0
58+
IL_002a: ldc.i4.s 99
59+
IL_002c: stind.i2
60+
IL_002d: ldloc.1
61+
IL_002e: ldc.i4.s 100
62+
IL_0030: stind.i2
63+
IL_0031: ldloc.2
64+
IL_0032: ldc.i4.s 101
65+
IL_0034: stind.i2
66+
IL_0035: ldnull
67+
IL_0036: stloc.3
68+
IL_0037: ldnull
69+
IL_0038: stloc.s 4
70+
IL_003a: ldnull
71+
IL_003b: stloc.s 5
72+
IL_003d: ret
73+
}
74+
}

ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs

+31-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2016 Daniel Grunwald
1+
// Copyright (c) 2016 Daniel Grunwald
22
//
33
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
44
// software and associated documentation files (the "Software"), to deal in the Software
@@ -878,28 +878,44 @@ void HandleStringToPointer(PinnedRegion pinnedRegion)
878878
}
879879
return;
880880
}
881-
if (body.EntryPoint.Instructions.Count != 3)
882-
{
883-
return;
884-
}
885-
886881
if (nativeVar.Type.GetStackType() != StackType.I)
887882
return;
888-
if (!initInst.UnwrapConv(ConversionKind.StopGCTracking).MatchLdLoc(pinnedRegion.Variable))
889-
return;
890-
if (!IsBranchOnNull(body.EntryPoint.Instructions[1], nativeVar, out Block targetBlock))
891-
return;
892-
if (!body.EntryPoint.Instructions[2].MatchBranch(out Block adjustOffsetToStringData))
893-
return;
894-
if (!(adjustOffsetToStringData.Parent == body && adjustOffsetToStringData.IncomingEdgeCount == 1
895-
&& IsOffsetToStringDataBlock(adjustOffsetToStringData, nativeVar, targetBlock)))
883+
884+
Block targetBlock;
885+
Block adjustOffsetToStringData = null;
886+
if (body.EntryPoint.Instructions.Count == 2)
887+
{
888+
if (!initInst.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out ILInstruction left, out ILInstruction right))
889+
return;
890+
if (!left.UnwrapConv(ConversionKind.StopGCTracking).MatchLdLoc(pinnedRegion.Variable))
891+
return;
892+
if (!IsOffsetToStringDataCall(right))
893+
return;
894+
if (!body.EntryPoint.Instructions[1].MatchBranch(out targetBlock))
895+
return;
896+
}
897+
else if (body.EntryPoint.Instructions.Count == 3)
898+
{
899+
if (!initInst.UnwrapConv(ConversionKind.StopGCTracking).MatchLdLoc(pinnedRegion.Variable))
900+
return;
901+
if (!IsBranchOnNull(body.EntryPoint.Instructions[1], nativeVar, out targetBlock))
902+
return;
903+
if (!body.EntryPoint.Instructions[2].MatchBranch(out adjustOffsetToStringData))
904+
return;
905+
if (!(adjustOffsetToStringData.Parent == body && adjustOffsetToStringData.IncomingEdgeCount == 1
906+
&& IsOffsetToStringDataBlock(adjustOffsetToStringData, nativeVar, targetBlock)))
907+
return;
908+
}
909+
else
896910
return;
911+
897912
context.Step("Handle pinned string (with adjustOffsetToStringData)", pinnedRegion);
898913
if (targetBlock.Parent == body)
899914
{
900915
// remove old entry point
901916
body.Blocks.RemoveAt(0);
902-
body.Blocks.RemoveAt(adjustOffsetToStringData.ChildIndex);
917+
if (adjustOffsetToStringData is not null)
918+
body.Blocks.RemoveAt(adjustOffsetToStringData.ChildIndex);
903919
// make targetBlock the new entry point
904920
body.Blocks.RemoveAt(targetBlock.ChildIndex);
905921
body.Blocks.Insert(0, targetBlock);

0 commit comments

Comments
 (0)