Skip to content

Commit 4f3af27

Browse files
committed
Add RoslynCompilerFix
1 parent d279203 commit 4f3af27

File tree

12 files changed

+407
-10
lines changed

12 files changed

+407
-10
lines changed

IncrementalCompiler.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalCompiler", "extra\
1717
EndProject
1818
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RoslynMdbWriter", "core\RoslynMdbWriter\RoslynMdbWriter.csproj", "{286226F3-564D-480A-B6C2-2D207CBFB064}"
1919
EndProject
20+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RoslynCompilerFix", "core\RoslynCompilerFix\RoslynCompilerFix.csproj", "{75048769-3DF1-40B6-9F3C-8D5C91501FBC}"
21+
EndProject
2022
Global
2123
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2224
Debug|Any CPU = Debug|Any CPU
@@ -43,6 +45,10 @@ Global
4345
{286226F3-564D-480A-B6C2-2D207CBFB064}.Debug|Any CPU.Build.0 = Debug|Any CPU
4446
{286226F3-564D-480A-B6C2-2D207CBFB064}.Release|Any CPU.ActiveCfg = Release|Any CPU
4547
{286226F3-564D-480A-B6C2-2D207CBFB064}.Release|Any CPU.Build.0 = Release|Any CPU
48+
{75048769-3DF1-40B6-9F3C-8D5C91501FBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49+
{75048769-3DF1-40B6-9F3C-8D5C91501FBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
50+
{75048769-3DF1-40B6-9F3C-8D5C91501FBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
51+
{75048769-3DF1-40B6-9F3C-8D5C91501FBC}.Release|Any CPU.Build.0 = Release|Any CPU
4652
EndGlobalSection
4753
GlobalSection(SolutionProperties) = preSolution
4854
HideSolutionNode = FALSE
@@ -53,5 +59,6 @@ Global
5359
{67FE81D8-C1BF-4D15-A512-E9E8078DEECF} = {A22672B3-D1C4-47C0-AB82-6D22BBB94BBB}
5460
{B19F1DAC-FA9A-4749-9E03-1848D29BFCCD} = {A22672B3-D1C4-47C0-AB82-6D22BBB94BBB}
5561
{286226F3-564D-480A-B6C2-2D207CBFB064} = {092669A2-567F-4C73-A01E-AEBA2C733994}
62+
{75048769-3DF1-40B6-9F3C-8D5C91501FBC} = {092669A2-567F-4C73-A01E-AEBA2C733994}
5663
EndGlobalSection
5764
EndGlobal

build.fsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,13 @@ Target "Build" (fun _ ->
3030

3131
Target "Package" (fun _ ->
3232
// pack IncrementalCompiler.exe with dependent module dlls to packed one
33-
let errorCode = Shell.Exec("./packages/ILRepack/tools/ILRepack.exe",
34-
"/wildcards /out:IncrementalCompiler.packed.exe IncrementalCompiler.exe *.dll",
35-
"./core/IncrementalCompiler/bin/Release")
33+
Shell.Exec("./packages/ILRepack/tools/ILRepack.exe",
34+
"/wildcards /out:IncrementalCompiler.packed.exe IncrementalCompiler.exe *.dll",
35+
"./core/IncrementalCompiler/bin/Release")
36+
// fix roslyn compiler to work well with UnityVS
37+
Shell.Exec("./core/RoslynCompilerFix/bin/Release/RoslynCompilerFix.exe",
38+
"IncrementalCompiler.packed.exe IncrementalCompiler.packed.exe",
39+
"./core/IncrementalCompiler/bin/Release")
3640
// let's make package
3741
for target in ["Unity4"; "Unity5"] do
3842
let targetDir = binDir @@ target

core/IncrementalCompiler/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@
2929
// You can specify all the values or you can default the Build and Revision Numbers
3030
// by using the '*' as shown below:
3131
// [assembly: AssemblyVersion("1.0.*")]
32-
[assembly: AssemblyVersion("1.1.2")]
33-
[assembly: AssemblyFileVersion("1.1.2")]
32+
[assembly: AssemblyVersion("1.1.3")]
33+
[assembly: AssemblyFileVersion("1.1.3")]

core/RoslynCompilerFix/App.config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
5+
</startup>
6+
</configuration>
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
using Mono.Cecil;
2+
using Mono.Cecil.Cil;
3+
using System;
4+
using System.Linq;
5+
using System.Text;
6+
7+
namespace RoslynCompilerFix
8+
{
9+
class CSharpCompilerFix
10+
{
11+
public static void Process(AssemblyDefinition assemblyDef)
12+
{
13+
foreach (var moduleDef in assemblyDef.Modules)
14+
{
15+
foreach (var type in moduleDef.Types)
16+
{
17+
if (type.FullName == "Microsoft.CodeAnalysis.CSharp.Symbols.GeneratedNames")
18+
{
19+
foreach (var method in type.Methods)
20+
{
21+
if (method.Name == "MakeHoistedLocalFieldName")
22+
Fix_GeneratedNames_MakeHoistedLocalFieldName(method);
23+
else if (method.Name == "MakeMethodScopedSynthesizedName")
24+
Fix_GeneratedNames_MakeMethodScopedSynthesizedName(method);
25+
else if (method.Name == "ThisProxyFieldName")
26+
Fix_GeneratedNames_ThisProxyFieldName(method);
27+
else if (method.Name == "MakeLambdaMethodName")
28+
Fix_GeneratedNames_MakeLambdaMethodName(method);
29+
}
30+
}
31+
else if (type.FullName == "Microsoft.CodeAnalysis.CSharp.LambdaFrame")
32+
{
33+
foreach (var method in type.Methods)
34+
{
35+
if (method.Name == ".ctor")
36+
Fix_LambdaFrame_Constructor(method);
37+
}
38+
}
39+
}
40+
}
41+
}
42+
43+
static void Fix_GeneratedNames_MakeHoistedLocalFieldName(MethodDefinition method)
44+
{
45+
// Goal:
46+
// Rename <v>4__1 to <v>__1 for local variables in iterator
47+
// How:
48+
// Remove following code from body of GeneratedNames.MakeHoistedLocalFieldName
49+
// IL_003c: ldloc.0
50+
// IL_003d: ldc.i4.s 53
51+
// IL_003f: callvirt System.Text.StringBuilder System.Text.StringBuilder::Append(System.Char)
52+
// IL_0044: pop
53+
54+
var il = method.Body.GetILProcessor();
55+
for (var i = 0; i < il.Body.Instructions.Count; i++)
56+
{
57+
var inst = il.Body.Instructions[i];
58+
if (inst.OpCode.Code == Code.Ldc_I4_S && (sbyte)inst.Operand == 53)
59+
{
60+
for (int j = 0; j < 4; j++)
61+
il.Remove(il.Body.Instructions[i + 2 - j]);
62+
break;
63+
}
64+
}
65+
}
66+
67+
static void Fix_GeneratedNames_MakeMethodScopedSynthesizedName(MethodDefinition method)
68+
{
69+
// Goal:
70+
// Rename <TestCoroutine>d__1 to <TestCoroutine>c__Iterator0 for iterator class name
71+
// How:
72+
// Append following code from MakeMethodScopedSynthesizedName
73+
// IL_0033: ldloc.0
74+
// IL_0034: ldc.i4.s 62
75+
// IL_0036: callvirt instance class [System.Runtime]System.Text.StringBuilder [System.Runtime]System.Text.StringBuilder::Append(char)
76+
// IL_003b: pop
77+
// IL_003c: ldloc.0
78+
// IL_003d: ldarg.0
79+
// IL_003e: conv.u2
80+
// IL_003f: callvirt instance class [System.Runtime]System.Text.StringBuilder [System.Runtime]System.Text.StringBuilder::Append(char)
81+
// IL_0044: pop
82+
// >> IL_?: ldarg.0
83+
// >> IL_?: ldc.i4.s 100
84+
// >> IL_?: bne.un.s OUT
85+
// >> IL_?: ldloc.0
86+
// >> IL_?: ldstr "__Iterator"
87+
// >> IL_?: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
88+
// >> IL_?: pop
89+
90+
var il = method.Body.GetILProcessor();
91+
for (var i = 0; i < il.Body.Instructions.Count; i++)
92+
{
93+
var inst = il.Body.Instructions[i];
94+
if (inst.OpCode.Code == Code.Ldc_I4_S && (sbyte)inst.Operand == 62)
95+
{
96+
var baseInst = il.Body.Instructions[i + 7];
97+
var baseInst2 = il.Body.Instructions[i + 8];
98+
var appendCharRef = ((MethodReference)il.Body.Instructions[i + 1].Operand);
99+
100+
var appendStringMethod = typeof(StringBuilder).GetMethod("Append", new Type[] { typeof(string) });
101+
var appendString = appendCharRef.DeclaringType.Module.Import(appendStringMethod);
102+
103+
il.InsertAfter(baseInst, il.Create(OpCodes.Pop));
104+
il.InsertAfter(baseInst, il.Create(OpCodes.Callvirt, appendString));
105+
il.InsertAfter(baseInst, il.Create(OpCodes.Ldstr, "__Iterator"));
106+
il.InsertAfter(baseInst, il.Create(OpCodes.Ldloc_0));
107+
il.InsertAfter(baseInst, il.Create(OpCodes.Bne_Un_S, baseInst2));
108+
il.InsertAfter(baseInst, il.Create(OpCodes.Ldc_I4_S, (sbyte)100));
109+
il.InsertAfter(baseInst, il.Create(OpCodes.Ldarg_0));
110+
break;
111+
}
112+
}
113+
}
114+
115+
static void Fix_GeneratedNames_ThisProxyFieldName(MethodDefinition method)
116+
{
117+
// Goal:
118+
// Rename <>4__this to <>f__this for this in iterator class
119+
// How:
120+
// Change literal "<>4__this" to "<>f__this" at ThisProxyFieldName()
121+
// IL_0000: ldstr "<>4__this"
122+
// IL_0005: ret
123+
124+
var il = method.Body.GetILProcessor();
125+
for (var i = 0; i < il.Body.Instructions.Count; i++)
126+
{
127+
var inst = il.Body.Instructions[i];
128+
if (inst.OpCode.Code == Code.Ldstr && (string)inst.Operand == "<>4__this")
129+
{
130+
il.Replace(inst, il.Create(OpCodes.Ldstr, "<>f__this"));
131+
break;
132+
}
133+
}
134+
}
135+
136+
static void Fix_LambdaFrame_Constructor(MethodDefinition method)
137+
{
138+
// Goal:
139+
// Rename <>c__DisplayClass0_0 to <*MethodName*>c__AnonStorey* for lambda class name
140+
// How:
141+
// IL_0000: ldarg.0
142+
// >> IL_?: ldstr "<"
143+
// >> IL_?: ldarg.0
144+
// >> IL_?: callvirt instance string Microsoft.CodeAnalysis.CSharp.Symbol::get_Name()
145+
// >> IL_?: ldstr ">c__AnonStorey"
146+
// IL_0001: ldarg.2
147+
// IL_0002: ldarg.3
148+
// IL_0003: ldarg.s closureId
149+
// IL_0005: call string Microsoft.CodeAnalysis.CSharp.LambdaFrame::MakeName(class Microsoft.CodeAnalysis.SyntaxNode, valuetype Microsoft.CodeAnalysis.CodeGen.DebugId, valuetype Microsoft.CodeAnalysis.CodeGen.DebugId)
150+
// >> IL_?: call string [mscorlib]System.String::Concat(string, string, string, string)
151+
// IL_000a: ldarg.1
152+
// IL_000b: call instance void Microsoft.CodeAnalysis.CSharp.Symbols.SynthesizedContainer::.ctor(string, class Microsoft.CodeAnalysis.CSharp.Symbols.MethodSymbol)
153+
154+
var il = method.Body.GetILProcessor();
155+
var baseInst = il.Body.Instructions[1];
156+
var baseInst2 = il.Body.Instructions[4];
157+
if (baseInst.OpCode.Code != Code.Ldarg_2)
158+
throw new InvalidOperationException();
159+
if (baseInst2.OpCode.Code != Code.Call)
160+
throw new InvalidOperationException();
161+
162+
var symbolType = method.Module.GetType("Microsoft.CodeAnalysis.CSharp.Symbol");
163+
var symbolGetNameMethod = symbolType.Methods.FirstOrDefault(m => m.Name == "get_Name");
164+
var symbolGetName = method.Module.Import(symbolGetNameMethod);
165+
166+
il.InsertBefore(baseInst, il.Create(OpCodes.Ldstr, "<"));
167+
il.InsertBefore(baseInst, il.Create(OpCodes.Ldarg_0));
168+
il.InsertBefore(baseInst, il.Create(OpCodes.Callvirt, symbolGetName));
169+
il.InsertBefore(baseInst, il.Create(OpCodes.Ldstr, ">c__AnonStorey"));
170+
171+
var concat4Method = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string), typeof(string), typeof(string) });
172+
var concat4 = method.Module.Import(concat4Method);
173+
174+
il.InsertAfter(baseInst2, il.Create(OpCodes.Call, concat4));
175+
}
176+
177+
static void Fix_GeneratedNames_MakeLambdaMethodName(MethodDefinition method)
178+
{
179+
// Goal:
180+
// Rename <Start>b__0 to <>m__<Start>b__0 for method name in lambda class
181+
// How:
182+
// >> IL_?: ldstr "<>m__"
183+
// IL_0000: ldc.i4.s 57
184+
// IL_0002: ldarg.0
185+
// IL_0003: ldarg.1
186+
// IL_0004: ldnull
187+
// IL_0005: ldnull
188+
// IL_0006: ldarg.2
189+
// IL_0007: ldarg.3
190+
// IL_0008: ldc.i4.0
191+
// IL_0009: call string Microsoft.CodeAnalysis.CSharp.Symbols.GeneratedNames::MakeMethodScopedSynthesizedName(valuetype Microsoft.CodeAnalysis.CSharp.Symbols.GeneratedNameKind, int32, int32, string, string, int32, int32, bool)
192+
// >> IL_?: call string [mscorlib]System.String::Concat(string, string)
193+
// IL_000e: ret
194+
195+
var il = method.Body.GetILProcessor();
196+
var baseInst = il.Body.Instructions[0];
197+
var baseInst2 = il.Body.Instructions[il.Body.Instructions.Count - 1];
198+
199+
var concatMethod = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) });
200+
var concat = method.Module.Import(concatMethod);
201+
202+
il.InsertBefore(baseInst, il.Create(OpCodes.Ldstr, "<>m__"));
203+
il.InsertBefore(baseInst2, il.Create(OpCodes.Call, concat));
204+
}
205+
}
206+
}

core/RoslynCompilerFix/Program.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using Mono.Cecil;
2+
using System;
3+
using System.IO;
4+
5+
namespace RoslynCompilerFix
6+
{
7+
class Program
8+
{
9+
static int Main(string[] args)
10+
{
11+
if (args.Length < 2)
12+
{
13+
Console.WriteLine("RoslynCompilerFix orignal-exe new-exe");
14+
return 1;
15+
}
16+
17+
ProcessDll(args[0], args[1]);
18+
Console.WriteLine("Done!");
19+
return 0;
20+
}
21+
22+
static void ProcessDll(string dllPath, string dllPathNew)
23+
{
24+
AssemblyDefinition assemblyDef;
25+
26+
using (var assemblyStream = new MemoryStream(File.ReadAllBytes(dllPath)))
27+
{
28+
assemblyDef = AssemblyDefinition.ReadAssembly(assemblyStream);
29+
}
30+
31+
CSharpCompilerFix.Process(assemblyDef);
32+
33+
using (var assemblyStream = File.Create(dllPathNew))
34+
{
35+
assemblyDef.Write(assemblyStream);
36+
}
37+
}
38+
}
39+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Reflection;
2+
using System.Runtime.InteropServices;
3+
4+
// General Information about an assembly is controlled through the following
5+
// set of attributes. Change these attribute values to modify the information
6+
// associated with an assembly.
7+
[assembly: AssemblyTitle("RoslynCompilerFix")]
8+
[assembly: AssemblyDescription("")]
9+
[assembly: AssemblyConfiguration("")]
10+
[assembly: AssemblyCompany("Saladbowl Creative")]
11+
[assembly: AssemblyProduct("Unity3D.IncrementalCompiler")]
12+
[assembly: AssemblyCopyright("Copyright © Saladbowl Creative 2016")]
13+
14+
// Setting ComVisible to false makes the types in this assembly not visible
15+
// to COM components. If you need to access a type in this assembly from
16+
// COM, set the ComVisible attribute to true on that type.
17+
[assembly: ComVisible(false)]
18+
19+
// The following GUID is for the ID of the typelib if this project is exposed to COM
20+
[assembly: Guid("75048769-3df1-40b6-9f3c-8d5c91501fbc")]
21+
22+
// Version information for an assembly consists of the following four values:
23+
//
24+
// Major Version
25+
// Minor Version
26+
// Build Number
27+
// Revision
28+
//
29+
// You can specify all the values or you can default the Build and Revision Numbers
30+
// by using the '*' as shown below:
31+
// [assembly: AssemblyVersion("1.0.*")]
32+
[assembly: AssemblyVersion("1.1.1")]
33+
[assembly: AssemblyFileVersion("1.1.1")]

0 commit comments

Comments
 (0)