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

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>2017-12-07 21:55:17 +0300
committerGitHub <noreply@github.com>2017-12-07 21:55:17 +0300
commit7ee9fb354edee4fb0846e2a3d5e64e7ec02c7f71 (patch)
treeda0d856519a734603421b4ae8d900595bae431c4 /src/ILCompiler.MetadataTransform
parentd56a610b3c890567feacf9492743a691ee3306e3 (diff)
Emit metadata for type forwarders (#5054)
Diffstat (limited to 'src/ILCompiler.MetadataTransform')
-rw-r--r--src/ILCompiler.MetadataTransform/src/ILCompiler.MetadataTransform.csproj1
-rw-r--r--src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Scope.cs67
-rw-r--r--src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.TypeForwarders.cs92
3 files changed, 134 insertions, 26 deletions
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler.MetadataTransform.csproj b/src/ILCompiler.MetadataTransform/src/ILCompiler.MetadataTransform.csproj
index 97f6e3ab3..2ecadbac2 100644
--- a/src/ILCompiler.MetadataTransform/src/ILCompiler.MetadataTransform.csproj
+++ b/src/ILCompiler.MetadataTransform/src/ILCompiler.MetadataTransform.csproj
@@ -32,6 +32,7 @@
<Compile Include="ILCompiler\Metadata\Transform.Scope.cs" />
<Compile Include="ILCompiler\Metadata\Transform.String.cs" />
<Compile Include="ILCompiler\Metadata\Transform.Type.cs" />
+ <Compile Include="ILCompiler\Metadata\Transform.TypeForwarders.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" Condition="'$(IsProjectNLibrary)' != 'true'"/>
</Project>
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Scope.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Scope.cs
index a518dcb85..406a61511 100644
--- a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Scope.cs
+++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Scope.cs
@@ -13,6 +13,7 @@ using Debug = System.Diagnostics.Debug;
using AssemblyFlags = Internal.Metadata.NativeFormat.AssemblyFlags;
using AssemblyNameFlags = System.Reflection.AssemblyNameFlags;
using AssemblyContentType = System.Reflection.AssemblyContentType;
+using AssemblyName = System.Reflection.AssemblyName;
namespace ILCompiler.Metadata
{
@@ -97,6 +98,8 @@ namespace ILCompiler.Metadata
{
scopeDefinition.ModuleCustomAttributes = HandleCustomAttributes(ecmaAssembly, moduleAttributes);
}
+
+ HandleTypeForwarders(ecmaAssembly);
}
}
else
@@ -105,45 +108,57 @@ namespace ILCompiler.Metadata
}
}
- private EntityMap<Cts.ModuleDesc, ScopeReference> _scopeRefs
- = new EntityMap<Cts.ModuleDesc, ScopeReference>(EqualityComparer<Cts.ModuleDesc>.Default);
- private Action<Cts.ModuleDesc, ScopeReference> _initScopeRef;
+ private EntityMap<AssemblyName, ScopeReference> _scopeRefs
+ = new EntityMap<AssemblyName, ScopeReference>(new SimpleAssemblyNameComparer());
+ private Action<AssemblyName, ScopeReference> _initScopeRef;
private ScopeReference HandleScopeReference(Cts.ModuleDesc module)
{
- return _scopeRefs.GetOrCreate(module, _initScopeRef ?? (_initScopeRef = InitializeScopeReference));
+ var assembly = module as Cts.IAssemblyDesc;
+ if (assembly != null)
+ return HandleScopeReference(assembly.GetName());
+ else
+ throw new NotSupportedException("Multi-module assemblies");
}
- private void InitializeScopeReference(Cts.ModuleDesc module, ScopeReference scopeReference)
+ private ScopeReference HandleScopeReference(AssemblyName assemblyName)
{
- var assemblyDesc = module as Cts.IAssemblyDesc;
- if (assemblyDesc != null)
- {
- var assemblyName = assemblyDesc.GetName();
+ return _scopeRefs.GetOrCreate(assemblyName, _initScopeRef ?? (_initScopeRef = InitializeScopeReference));
+ }
- scopeReference.Name = HandleString(assemblyName.Name);
- scopeReference.Culture = HandleString(assemblyName.CultureName);
- scopeReference.MajorVersion = checked((ushort)assemblyName.Version.Major);
- scopeReference.MinorVersion = checked((ushort)assemblyName.Version.Minor);
- scopeReference.BuildNumber = checked((ushort)assemblyName.Version.Build);
- scopeReference.RevisionNumber = checked((ushort)assemblyName.Version.Revision);
+ private void InitializeScopeReference(AssemblyName assemblyName, ScopeReference scopeReference)
+ {
+ scopeReference.Name = HandleString(assemblyName.Name);
+ scopeReference.Culture = HandleString(assemblyName.CultureName);
+ scopeReference.MajorVersion = checked((ushort)assemblyName.Version.Major);
+ scopeReference.MinorVersion = checked((ushort)assemblyName.Version.Minor);
+ scopeReference.BuildNumber = checked((ushort)assemblyName.Version.Build);
+ scopeReference.RevisionNumber = checked((ushort)assemblyName.Version.Revision);
- Debug.Assert((int)AssemblyFlags.PublicKey == (int)AssemblyNameFlags.PublicKey);
- Debug.Assert((int)AssemblyFlags.Retargetable == (int)AssemblyNameFlags.Retargetable);
+ Debug.Assert((int)AssemblyFlags.PublicKey == (int)AssemblyNameFlags.PublicKey);
+ Debug.Assert((int)AssemblyFlags.Retargetable == (int)AssemblyNameFlags.Retargetable);
- // References use a public key token instead of full public key.
- scopeReference.Flags = (AssemblyFlags)(assemblyName.Flags & ~AssemblyNameFlags.PublicKey);
+ // References use a public key token instead of full public key.
+ scopeReference.Flags = (AssemblyFlags)(assemblyName.Flags & ~AssemblyNameFlags.PublicKey);
- if (assemblyName.ContentType == AssemblyContentType.WindowsRuntime)
- {
- scopeReference.Flags |= (AssemblyFlags)((int)AssemblyContentType.WindowsRuntime << 9);
- }
+ if (assemblyName.ContentType == AssemblyContentType.WindowsRuntime)
+ {
+ scopeReference.Flags |= (AssemblyFlags)((int)AssemblyContentType.WindowsRuntime << 9);
+ }
+
+ scopeReference.PublicKeyOrToken = assemblyName.GetPublicKeyToken();
+ }
- scopeReference.PublicKeyOrToken = assemblyName.GetPublicKeyToken();
+ private class SimpleAssemblyNameComparer : IEqualityComparer<AssemblyName>
+ {
+ public bool Equals(AssemblyName x, AssemblyName y)
+ {
+ return Object.Equals(x.Name, y.Name);
}
- else
+
+ public int GetHashCode(AssemblyName obj)
{
- throw new NotSupportedException("Multi-module assemblies");
+ return obj.Name?.GetHashCode() ?? 0;
}
}
}
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.TypeForwarders.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.TypeForwarders.cs
new file mode 100644
index 000000000..be03c1d73
--- /dev/null
+++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.TypeForwarders.cs
@@ -0,0 +1,92 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+using Internal.Metadata.NativeFormat.Writer;
+
+using Cts = Internal.TypeSystem;
+using Ecma = System.Reflection.Metadata;
+
+using Debug = System.Diagnostics.Debug;
+using AssemblyName = System.Reflection.AssemblyName;
+using AssemblyContentType = System.Reflection.AssemblyContentType;
+using AssemblyNameFlags = System.Reflection.AssemblyNameFlags;
+using AssemblyFlags = System.Reflection.AssemblyFlags;
+
+namespace ILCompiler.Metadata
+{
+ partial class Transform<TPolicy>
+ {
+ private void HandleTypeForwarders(Cts.Ecma.EcmaModule module)
+ {
+ foreach (var exportedTypeHandle in module.MetadataReader.ExportedTypes)
+ {
+ Ecma.ExportedType exportedType = module.MetadataReader.GetExportedType(exportedTypeHandle);
+ if (exportedType.IsForwarder || exportedType.Implementation.Kind == Ecma.HandleKind.ExportedType)
+ {
+ HandleTypeForwarder(module, exportedType);
+ }
+ else
+ {
+ Debug.Assert(false, "Multi-module assemblies");
+ }
+ }
+ }
+
+ private TypeForwarder HandleTypeForwarder(Cts.Ecma.EcmaModule module, Ecma.ExportedType exportedType)
+ {
+ Ecma.MetadataReader reader = module.MetadataReader;
+ string name = reader.GetString(exportedType.Name);
+ TypeForwarder result;
+
+ switch (exportedType.Implementation.Kind)
+ {
+ case Ecma.HandleKind.AssemblyReference:
+ {
+ string ns = reader.GetString(exportedType.Namespace);
+ NamespaceDefinition namespaceDefinition = HandleNamespaceDefinition(module, ns);
+
+ Ecma.AssemblyReference assemblyRef = reader.GetAssemblyReference((Ecma.AssemblyReferenceHandle)exportedType.Implementation);
+ AssemblyName refName = new AssemblyName
+ {
+ ContentType = (AssemblyContentType)((int)(assemblyRef.Flags & AssemblyFlags.ContentTypeMask) >> 9),
+ Flags = (AssemblyNameFlags)(assemblyRef.Flags & ~AssemblyFlags.ContentTypeMask),
+ CultureName = reader.GetString(assemblyRef.Culture),
+ Name = reader.GetString(assemblyRef.Name),
+ Version = assemblyRef.Version,
+ };
+
+ result = new TypeForwarder
+ {
+ Name = HandleString(name),
+ Scope = HandleScopeReference(refName),
+ };
+
+ namespaceDefinition.TypeForwarders.Add(result);
+ }
+ break;
+
+ case Ecma.HandleKind.ExportedType:
+ {
+ TypeForwarder scope = HandleTypeForwarder(module, reader.GetExportedType((Ecma.ExportedTypeHandle)exportedType.Implementation));
+
+ result = new TypeForwarder
+ {
+ Name = HandleString(name),
+ Scope = scope.Scope,
+ };
+
+ scope.NestedTypes.Add(result);
+ }
+ break;
+
+ default:
+ throw new BadImageFormatException();
+ }
+
+ return result;
+ }
+ }
+}