Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
Expand Down
45 changes: 41 additions & 4 deletions source/MetadataProcessor.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ private sealed class MetadataProcessor

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

internal bool Minimize { get; set; }
internal string PeFileName;

internal bool Verbose { get; set; }

internal bool VerboseMinimize { get; set; }

public void Parse(string fileName)
{
try
Expand All @@ -56,7 +58,7 @@ public void Compile(
{
if (Verbose) System.Console.WriteLine("Compiling assembly...");

_assemblyBuilder = new nanoAssemblyBuilder(_assemblyDefinition, _classNamesToExclude, Minimize, Verbose, isCoreLibrary);
_assemblyBuilder = new nanoAssemblyBuilder(_assemblyDefinition, _classNamesToExclude, VerboseMinimize, isCoreLibrary);

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

public void Minimize(
string fileName)
{
try
{
if (Verbose) System.Console.WriteLine("Minimizing assembly...");

_assemblyBuilder.Minimize();

using (var stream = File.Open(fileName, FileMode.Create, FileAccess.ReadWrite))
using (var writer = new BinaryWriter(stream))
{
_assemblyBuilder.Write(GetBinaryWriter(writer));
}

using (var writer = XmlWriter.Create(Path.ChangeExtension(fileName, "pdbx")))
{
_assemblyBuilder.Write(writer);
}
}
catch (Exception ex)
{
System.Console.Error.WriteLine(
"Unable to minimize assembly file '{0}'.", fileName);
throw;
}
}

private nanoBinaryWriter GetBinaryWriter(BinaryWriter writer)
{
return nanoBinaryWriter.CreateLittleEndianBinaryWriter(writer);
Expand Down Expand Up @@ -189,6 +219,7 @@ public static void Main(string[] args)
System.Console.WriteLine("-generateDependency Generates an XML file with the relationship between assemblies.");
System.Console.WriteLine("-minimize Minimizes the assembly, removing unwanted elements.");
System.Console.WriteLine("-verbose Outputs each command before executing it.");
System.Console.WriteLine("-verboseMinimize Turns on verbose level for the minimization phase.");
System.Console.WriteLine("");
}
else if (arg == "-parse" && i + 1 < args.Length)
Expand All @@ -206,7 +237,9 @@ public static void Main(string[] args)
Environment.Exit(1);
}

md.Compile(args[i + 1], isCoreLibrary);
md.PeFileName = args[i + 1];

md.Compile(md.PeFileName, isCoreLibrary);

i += 2;
}
Expand All @@ -216,12 +249,16 @@ public static void Main(string[] args)
}
else if (arg == "-minimize" && i + 1 < args.Length)
{
md.Minimize = true;
md.Minimize(md.PeFileName);
}
else if (arg == "-verbose" && i + 1 < args.Length)
{
md.Verbose = true;
}
else if (arg == "-verboseminimize" && i + 1 < args.Length)
{
md.VerboseMinimize = true;
}
else if (arg == "-loadhints" && i + 2 < args.Length)
{
md.AddLoadHint(args[i + 1], args[i + 2]);
Expand Down
3 changes: 0 additions & 3 deletions source/MetadataProcessor.Console/app.config

This file was deleted.

22 changes: 16 additions & 6 deletions source/MetadataProcessor.Core/MetadataProcessor.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,25 @@
<HintPath>..\packages\Stubble.Core.1.7.2\lib\net45\Stubble.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.2.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll</HintPath>
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Collections.Immutable, Version=1.2.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.7.0\lib\netstandard2.0\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.7.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
Expand Down
7 changes: 6 additions & 1 deletion source/MetadataProcessor.Core/Mono.Cecil/CodeWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,12 @@ private ushort GetTypeReferenceId(
ushort typeReferenceMask = 0x4000)
{
ushort referenceId;
if (_context.TypeReferencesTable.TryGetTypeReferenceId(typeReference, out referenceId))

if(typeReference is TypeSpecification)
{
referenceId = _context.TypeSpecificationsTable.GetOrCreateTypeSpecificationId(typeReference);
}
else if (_context.TypeReferencesTable.TryGetTypeReferenceId(typeReference, out referenceId))
{
referenceId |= typeReferenceMask; // External type reference
}
Expand Down
22 changes: 19 additions & 3 deletions source/MetadataProcessor.Core/Tables/nanoByteCodeTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace nanoFramework.Tools.MetadataProcessor
{
Expand Down Expand Up @@ -83,7 +84,12 @@ public ushort GetMethodId(
_methods.Add(method);
_lastAvailableRva += (ushort)byteCode.Length;

_rvasByMethodNames.Add(method.FullName, rva);
// need to check if table already has this key (because of second pass to minimize)
if (!_rvasByMethodNames.ContainsKey(method.FullName))
{
_rvasByMethodNames.Add(method.FullName, rva);
}

return id;
}

Expand All @@ -105,9 +111,19 @@ public ushort GetMethodRva(
public void Write(
nanoBinaryWriter writer)
{
foreach (var method in _methods)
if (_context.UsedElements != null)
{
foreach (var method in _methods.Where(item => _context.UsedElements.Contains(item.MetadataToken)))
{
writer.WriteBytes(CreateByteCode(method, writer));
}
}
else
{
writer.WriteBytes(CreateByteCode(method, writer));
foreach (var method in _methods)
{
writer.WriteBytes(CreateByteCode(method, writer));
}
}
}

Expand Down
45 changes: 26 additions & 19 deletions source/MetadataProcessor.Core/Tables/nanoMethodDefinitionTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,11 @@ protected override void WriteSingleItem(
// This check is wrong. A TypeSpecification is showing when the return type it's an array which is OK.
// Requires further investigation to evaluate what's the correct condition required to add an entry to the Type Specifications Table

//_context.TypeSpecificationsTable
// .GetOrCreateTypeSpecificationId(item.ReturnType);
//if (!item.ReturnType.GetElementType().IsPrimitive &&
// item.ReturnType.GetElementType().FullName != "System.Object")
//{
// _context.TypeSpecificationsTable.GetOrCreateTypeSpecificationId(item.ReturnType);
//}
}

writer.WriteByte(parametersCount);
Expand Down Expand Up @@ -234,7 +237,8 @@ private uint GetFlags(
//flag |= MD_HasAttributes; // ???
}

if (method == method.Module.EntryPoint)
if (method.Module != null &&
method == method.Module.EntryPoint)
{
flag |= MD_EntryPoint;
}
Expand All @@ -244,24 +248,27 @@ private uint GetFlags(
flag |= MD_HasExceptionHandlers;
}

var baseType = method.DeclaringType.BaseType;
if (baseType != null && baseType.FullName == "System.MulticastDelegate")
if (method.DeclaringType != null)
{
if (method.IsConstructor)
var baseType = method.DeclaringType.BaseType;
if (baseType != null && baseType.FullName == "System.MulticastDelegate")
{
flag |= MD_DelegateConstructor;
}
else if (method.Name == "Invoke")
{
flag |= MD_DelegateInvoke;
}
else if (method.Name == "BeginInvoke")
{
flag |= MD_DelegateBeginInvoke;
}
else if (method.Name == "EndInvoke")
{
flag |= MD_DelegateEndInvoke;
if (method.IsConstructor)
{
flag |= MD_DelegateConstructor;
}
else if (method.Name == "Invoke")
{
flag |= MD_DelegateInvoke;
}
else if (method.Name == "BeginInvoke")
{
flag |= MD_DelegateBeginInvoke;
}
else if (method.Name == "EndInvoke")
{
flag |= MD_DelegateEndInvoke;
}
}
}

Expand Down
68 changes: 63 additions & 5 deletions source/MetadataProcessor.Core/Tables/nanoReferenceTableBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// See LICENSE file in the project root for full license information.
//

using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -26,7 +27,7 @@ public abstract class nanoReferenceTableBase<T> : InanoTable
/// Assembly tables context - contains all tables used for building target assembly.
/// </summary>
protected readonly nanoTablesContext _context;

/// <summary>
/// Lookup table for finding item ID by item value.
/// </summary>
Expand Down Expand Up @@ -61,11 +62,24 @@ protected nanoReferenceTableBase(
public void Write(
nanoBinaryWriter writer)
{
foreach (var item in _idsByItemsDictionary
.OrderBy(item => item.Value)
.Select(item => item.Key))
if (_context.UsedElements != null)
{
WriteSingleItem(writer, item);
foreach (var item in _idsByItemsDictionary
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken))
.OrderBy(item => item.Value)
.Select(item => item.Key))
{
WriteSingleItem(writer, item);
}
}
else
{
foreach (var item in _idsByItemsDictionary
.OrderBy(item => item.Value)
.Select(item => item.Key))
{
WriteSingleItem(writer, item);
}
}
}

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

public void ForEachItemInUse(Action<uint, T> action)
{
foreach (var item in _idsByItemsDictionary
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken))
.OrderBy(item => item.Value))
{
action(item.Value, item.Key);
}
}

/// <summary>
/// Helper method for allocating strings from table before table will be written.
/// </summary>
Expand All @@ -90,6 +114,16 @@ public void AllocateStrings()
AllocateSingleItemStrings(item);
}
}
public void AllocateStringsInUse()
{
foreach (var item in _idsByItemsDictionary
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken))
.OrderBy(item => item.Value)
.Select(item => item.Key))
{
AllocateSingleItemStrings(item);
}
}

/// <summary>
/// Writes string reference ID related to passed string value into output stream.
Expand Down Expand Up @@ -144,5 +178,29 @@ protected virtual void AllocateSingleItemStrings(T item)
protected abstract void WriteSingleItem(
nanoBinaryWriter writer,
T item);

public IEnumerable<T> GetUsedItems()
{
List<T> usedItems = new List<T>();

if (_context.UsedElements != null)
{

foreach (var item in _idsByItemsDictionary
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken)))
{
usedItems.Add(item.Key);
}
}
else
{
foreach (var item in _idsByItemsDictionary)
{
usedItems.Add(item.Key);
}
}

return usedItems;
}
}
}
Loading