Skip to content

Commit 5a9477b

Browse files
authored
Add minimize and verbose parameters (#31)
1 parent 3add8b2 commit 5a9477b

18 files changed

+802
-69
lines changed

source/MetadataProcessor.Console/MetadataProcessor.Console.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
</ItemGroup>
5858
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
5959
<ItemGroup>
60-
<None Include="app.config" />
6160
<None Include="packages.config" />
6261
</ItemGroup>
6362
<ItemGroup>

source/MetadataProcessor.Console/Program.cs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ private sealed class MetadataProcessor
2727

2828
private List<string> _classNamesToExclude = new List<string>();
2929

30-
internal bool Minimize { get; set; }
30+
internal string PeFileName;
3131

3232
internal bool Verbose { get; set; }
3333

34+
internal bool VerboseMinimize { get; set; }
35+
3436
public void Parse(string fileName)
3537
{
3638
try
@@ -56,7 +58,7 @@ public void Compile(
5658
{
5759
if (Verbose) System.Console.WriteLine("Compiling assembly...");
5860

59-
_assemblyBuilder = new nanoAssemblyBuilder(_assemblyDefinition, _classNamesToExclude, Minimize, Verbose, isCoreLibrary);
61+
_assemblyBuilder = new nanoAssemblyBuilder(_assemblyDefinition, _classNamesToExclude, VerboseMinimize, isCoreLibrary);
6062

6163
using (var stream = File.Open(fileName, FileMode.Create, FileAccess.ReadWrite))
6264
using (var writer = new BinaryWriter(stream))
@@ -77,6 +79,34 @@ public void Compile(
7779
}
7880
}
7981

82+
public void Minimize(
83+
string fileName)
84+
{
85+
try
86+
{
87+
if (Verbose) System.Console.WriteLine("Minimizing assembly...");
88+
89+
_assemblyBuilder.Minimize();
90+
91+
using (var stream = File.Open(fileName, FileMode.Create, FileAccess.ReadWrite))
92+
using (var writer = new BinaryWriter(stream))
93+
{
94+
_assemblyBuilder.Write(GetBinaryWriter(writer));
95+
}
96+
97+
using (var writer = XmlWriter.Create(Path.ChangeExtension(fileName, "pdbx")))
98+
{
99+
_assemblyBuilder.Write(writer);
100+
}
101+
}
102+
catch (Exception ex)
103+
{
104+
System.Console.Error.WriteLine(
105+
"Unable to minimize assembly file '{0}'.", fileName);
106+
throw;
107+
}
108+
}
109+
80110
private nanoBinaryWriter GetBinaryWriter(BinaryWriter writer)
81111
{
82112
return nanoBinaryWriter.CreateLittleEndianBinaryWriter(writer);
@@ -189,6 +219,7 @@ public static void Main(string[] args)
189219
System.Console.WriteLine("-generateDependency Generates an XML file with the relationship between assemblies.");
190220
System.Console.WriteLine("-minimize Minimizes the assembly, removing unwanted elements.");
191221
System.Console.WriteLine("-verbose Outputs each command before executing it.");
222+
System.Console.WriteLine("-verboseMinimize Turns on verbose level for the minimization phase.");
192223
System.Console.WriteLine("");
193224
}
194225
else if (arg == "-parse" && i + 1 < args.Length)
@@ -206,7 +237,9 @@ public static void Main(string[] args)
206237
Environment.Exit(1);
207238
}
208239

209-
md.Compile(args[i + 1], isCoreLibrary);
240+
md.PeFileName = args[i + 1];
241+
242+
md.Compile(md.PeFileName, isCoreLibrary);
210243

211244
i += 2;
212245
}
@@ -216,12 +249,16 @@ public static void Main(string[] args)
216249
}
217250
else if (arg == "-minimize" && i + 1 < args.Length)
218251
{
219-
md.Minimize = true;
252+
md.Minimize(md.PeFileName);
220253
}
221254
else if (arg == "-verbose" && i + 1 < args.Length)
222255
{
223256
md.Verbose = true;
224257
}
258+
else if (arg == "-verboseminimize" && i + 1 < args.Length)
259+
{
260+
md.VerboseMinimize = true;
261+
}
225262
else if (arg == "-loadhints" && i + 2 < args.Length)
226263
{
227264
md.AddLoadHint(args[i + 1], args[i + 2]);

source/MetadataProcessor.Console/app.config

Lines changed: 0 additions & 3 deletions
This file was deleted.

source/MetadataProcessor.Core/MetadataProcessor.Core.csproj

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,25 @@
5656
<HintPath>..\packages\Stubble.Core.1.7.2\lib\net45\Stubble.Core.dll</HintPath>
5757
</Reference>
5858
<Reference Include="System" />
59-
<Reference Include="System.Collections.Immutable, Version=1.2.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
60-
<HintPath>..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll</HintPath>
59+
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
60+
<HintPath>..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
61+
</Reference>
62+
<Reference Include="System.Collections.Immutable, Version=1.2.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
63+
<HintPath>..\packages\System.Collections.Immutable.1.7.0\lib\netstandard2.0\System.Collections.Immutable.dll</HintPath>
6164
</Reference>
6265
<Reference Include="System.Drawing" />
63-
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
64-
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
66+
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
67+
<HintPath>..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath>
68+
</Reference>
69+
<Reference Include="System.Numerics" />
70+
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
71+
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
72+
</Reference>
73+
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
74+
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.7.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
6575
</Reference>
66-
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
67-
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
76+
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
77+
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
6878
</Reference>
6979
<Reference Include="System.Windows.Forms" />
7080
<Reference Include="System.Xml" />

source/MetadataProcessor.Core/Mono.Cecil/CodeWriter.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,12 @@ private ushort GetTypeReferenceId(
469469
ushort typeReferenceMask = 0x4000)
470470
{
471471
ushort referenceId;
472-
if (_context.TypeReferencesTable.TryGetTypeReferenceId(typeReference, out referenceId))
472+
473+
if(typeReference is TypeSpecification)
474+
{
475+
referenceId = _context.TypeSpecificationsTable.GetOrCreateTypeSpecificationId(typeReference);
476+
}
477+
else if (_context.TypeReferencesTable.TryGetTypeReferenceId(typeReference, out referenceId))
473478
{
474479
referenceId |= typeReferenceMask; // External type reference
475480
}

source/MetadataProcessor.Core/Tables/nanoByteCodeTable.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System;
99
using System.Collections.Generic;
1010
using System.IO;
11+
using System.Linq;
1112

1213
namespace nanoFramework.Tools.MetadataProcessor
1314
{
@@ -83,7 +84,12 @@ public ushort GetMethodId(
8384
_methods.Add(method);
8485
_lastAvailableRva += (ushort)byteCode.Length;
8586

86-
_rvasByMethodNames.Add(method.FullName, rva);
87+
// need to check if table already has this key (because of second pass to minimize)
88+
if (!_rvasByMethodNames.ContainsKey(method.FullName))
89+
{
90+
_rvasByMethodNames.Add(method.FullName, rva);
91+
}
92+
8793
return id;
8894
}
8995

@@ -105,9 +111,19 @@ public ushort GetMethodRva(
105111
public void Write(
106112
nanoBinaryWriter writer)
107113
{
108-
foreach (var method in _methods)
114+
if (_context.UsedElements != null)
115+
{
116+
foreach (var method in _methods.Where(item => _context.UsedElements.Contains(item.MetadataToken)))
117+
{
118+
writer.WriteBytes(CreateByteCode(method, writer));
119+
}
120+
}
121+
else
109122
{
110-
writer.WriteBytes(CreateByteCode(method, writer));
123+
foreach (var method in _methods)
124+
{
125+
writer.WriteBytes(CreateByteCode(method, writer));
126+
}
111127
}
112128
}
113129

source/MetadataProcessor.Core/Tables/nanoMethodDefinitionTable.cs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,11 @@ protected override void WriteSingleItem(
8080
// This check is wrong. A TypeSpecification is showing when the return type it's an array which is OK.
8181
// Requires further investigation to evaluate what's the correct condition required to add an entry to the Type Specifications Table
8282

83-
//_context.TypeSpecificationsTable
84-
// .GetOrCreateTypeSpecificationId(item.ReturnType);
83+
//if (!item.ReturnType.GetElementType().IsPrimitive &&
84+
// item.ReturnType.GetElementType().FullName != "System.Object")
85+
//{
86+
// _context.TypeSpecificationsTable.GetOrCreateTypeSpecificationId(item.ReturnType);
87+
//}
8588
}
8689

8790
writer.WriteByte(parametersCount);
@@ -234,7 +237,8 @@ private uint GetFlags(
234237
//flag |= MD_HasAttributes; // ???
235238
}
236239

237-
if (method == method.Module.EntryPoint)
240+
if (method.Module != null &&
241+
method == method.Module.EntryPoint)
238242
{
239243
flag |= MD_EntryPoint;
240244
}
@@ -244,24 +248,27 @@ private uint GetFlags(
244248
flag |= MD_HasExceptionHandlers;
245249
}
246250

247-
var baseType = method.DeclaringType.BaseType;
248-
if (baseType != null && baseType.FullName == "System.MulticastDelegate")
251+
if (method.DeclaringType != null)
249252
{
250-
if (method.IsConstructor)
253+
var baseType = method.DeclaringType.BaseType;
254+
if (baseType != null && baseType.FullName == "System.MulticastDelegate")
251255
{
252-
flag |= MD_DelegateConstructor;
253-
}
254-
else if (method.Name == "Invoke")
255-
{
256-
flag |= MD_DelegateInvoke;
257-
}
258-
else if (method.Name == "BeginInvoke")
259-
{
260-
flag |= MD_DelegateBeginInvoke;
261-
}
262-
else if (method.Name == "EndInvoke")
263-
{
264-
flag |= MD_DelegateEndInvoke;
256+
if (method.IsConstructor)
257+
{
258+
flag |= MD_DelegateConstructor;
259+
}
260+
else if (method.Name == "Invoke")
261+
{
262+
flag |= MD_DelegateInvoke;
263+
}
264+
else if (method.Name == "BeginInvoke")
265+
{
266+
flag |= MD_DelegateBeginInvoke;
267+
}
268+
else if (method.Name == "EndInvoke")
269+
{
270+
flag |= MD_DelegateEndInvoke;
271+
}
265272
}
266273
}
267274

source/MetadataProcessor.Core/Tables/nanoReferenceTableBase.cs

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// See LICENSE file in the project root for full license information.
55
//
66

7+
using Mono.Cecil;
78
using System;
89
using System.Collections.Generic;
910
using System.Linq;
@@ -26,7 +27,7 @@ public abstract class nanoReferenceTableBase<T> : InanoTable
2627
/// Assembly tables context - contains all tables used for building target assembly.
2728
/// </summary>
2829
protected readonly nanoTablesContext _context;
29-
30+
3031
/// <summary>
3132
/// Lookup table for finding item ID by item value.
3233
/// </summary>
@@ -61,11 +62,24 @@ protected nanoReferenceTableBase(
6162
public void Write(
6263
nanoBinaryWriter writer)
6364
{
64-
foreach (var item in _idsByItemsDictionary
65-
.OrderBy(item => item.Value)
66-
.Select(item => item.Key))
65+
if (_context.UsedElements != null)
6766
{
68-
WriteSingleItem(writer, item);
67+
foreach (var item in _idsByItemsDictionary
68+
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken))
69+
.OrderBy(item => item.Value)
70+
.Select(item => item.Key))
71+
{
72+
WriteSingleItem(writer, item);
73+
}
74+
}
75+
else
76+
{
77+
foreach (var item in _idsByItemsDictionary
78+
.OrderBy(item => item.Value)
79+
.Select(item => item.Key))
80+
{
81+
WriteSingleItem(writer, item);
82+
}
6983
}
7084
}
7185

@@ -78,6 +92,16 @@ public void ForEachItems(Action<uint, T> action)
7892
}
7993
}
8094

95+
public void ForEachItemInUse(Action<uint, T> action)
96+
{
97+
foreach (var item in _idsByItemsDictionary
98+
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken))
99+
.OrderBy(item => item.Value))
100+
{
101+
action(item.Value, item.Key);
102+
}
103+
}
104+
81105
/// <summary>
82106
/// Helper method for allocating strings from table before table will be written.
83107
/// </summary>
@@ -90,6 +114,16 @@ public void AllocateStrings()
90114
AllocateSingleItemStrings(item);
91115
}
92116
}
117+
public void AllocateStringsInUse()
118+
{
119+
foreach (var item in _idsByItemsDictionary
120+
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken))
121+
.OrderBy(item => item.Value)
122+
.Select(item => item.Key))
123+
{
124+
AllocateSingleItemStrings(item);
125+
}
126+
}
93127

94128
/// <summary>
95129
/// Writes string reference ID related to passed string value into output stream.
@@ -144,5 +178,29 @@ protected virtual void AllocateSingleItemStrings(T item)
144178
protected abstract void WriteSingleItem(
145179
nanoBinaryWriter writer,
146180
T item);
181+
182+
public IEnumerable<T> GetUsedItems()
183+
{
184+
List<T> usedItems = new List<T>();
185+
186+
if (_context.UsedElements != null)
187+
{
188+
189+
foreach (var item in _idsByItemsDictionary
190+
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken)))
191+
{
192+
usedItems.Add(item.Key);
193+
}
194+
}
195+
else
196+
{
197+
foreach (var item in _idsByItemsDictionary)
198+
{
199+
usedItems.Add(item.Key);
200+
}
201+
}
202+
203+
return usedItems;
204+
}
147205
}
148206
}

0 commit comments

Comments
 (0)