You've already forked linux-packaging-mono
Imported Upstream version 5.10.0.69
Former-commit-id: fc39669a0b707dd3c063977486506b6793da2890
This commit is contained in:
parent
d8f8abd549
commit
e2950ec768
149
external/corert/src/ILCompiler.Compiler/ILCompiler.Compiler.sln
vendored
Normal file
149
external/corert/src/ILCompiler.Compiler/ILCompiler.Compiler.sln
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26430.16
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Compiler.Tests", "tests\ILCompiler.Compiler.Tests.csproj", "{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Compiler", "src\ILCompiler.Compiler.csproj", "{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.TypeSystem", "..\ILCompiler.TypeSystem\src\ILCompiler.TypeSystem.csproj", "{846B4638-43AE-452F-B171-D8DB600F1284}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILCompiler.Compiler.Tests.Assets", "tests\ILCompiler.Compiler.Tests.Assets\ILCompiler.Compiler.Tests.Assets.csproj", "{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.CoreLib", "..\Test.CoreLib\src\Test.CoreLib.csproj", "{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|arm = Debug|arm
|
||||
Debug|arm64 = Debug|arm64
|
||||
Debug|armel = Debug|armel
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|arm = Release|arm
|
||||
Release|arm64 = Release|arm64
|
||||
Release|armel = Release|armel
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|arm.ActiveCfg = Debug|arm
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|arm.Build.0 = Debug|arm
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|arm64.ActiveCfg = Debug|arm64
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|arm64.Build.0 = Debug|arm64
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|armel.ActiveCfg = Debug|armel
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|armel.Build.0 = Debug|armel
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|x64.Build.0 = Debug|x64
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|x86.Build.0 = Debug|x86
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|arm.ActiveCfg = Release|arm
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|arm.Build.0 = Release|arm
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|arm64.ActiveCfg = Release|arm64
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|arm64.Build.0 = Release|arm64
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|armel.ActiveCfg = Release|armel
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|armel.Build.0 = Release|armel
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|x64.ActiveCfg = Release|x64
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|x64.Build.0 = Release|x64
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|x86.ActiveCfg = Release|x86
|
||||
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|x86.Build.0 = Release|x86
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|arm.ActiveCfg = Debug|arm
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|arm.Build.0 = Debug|arm
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|arm64.ActiveCfg = Debug|arm64
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|arm64.Build.0 = Debug|arm64
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|armel.ActiveCfg = Debug|armel
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|armel.Build.0 = Debug|armel
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|x64.Build.0 = Debug|x64
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|x86.Build.0 = Debug|x86
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|arm.ActiveCfg = Release|arm
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|arm.Build.0 = Release|arm
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|arm64.ActiveCfg = Release|arm64
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|arm64.Build.0 = Release|arm64
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|armel.ActiveCfg = Release|armel
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|armel.Build.0 = Release|armel
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|x64.ActiveCfg = Release|x64
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|x64.Build.0 = Release|x64
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|x86.ActiveCfg = Release|x86
|
||||
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|x86.Build.0 = Release|x86
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|arm.ActiveCfg = Debug|arm
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|arm.Build.0 = Debug|arm
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|arm64.ActiveCfg = Debug|arm64
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|arm64.Build.0 = Debug|arm64
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|armel.ActiveCfg = Debug|armel
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|armel.Build.0 = Debug|armel
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|x64.Build.0 = Debug|x64
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|x86.Build.0 = Debug|x86
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|arm.ActiveCfg = Release|arm
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|arm.Build.0 = Release|arm
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|arm64.ActiveCfg = Release|arm64
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|arm64.Build.0 = Release|arm64
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|armel.ActiveCfg = Release|armel
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|armel.Build.0 = Release|armel
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|x64.ActiveCfg = Release|x64
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|x64.Build.0 = Release|x64
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|x86.ActiveCfg = Release|x86
|
||||
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|x86.Build.0 = Release|x86
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|arm.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|arm.Build.0 = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|arm64.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|arm64.Build.0 = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|armel.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|armel.Build.0 = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|Any CPU.Build.0 = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|arm.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|arm.Build.0 = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|arm64.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|arm64.Build.0 = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|armel.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|armel.Build.0 = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|x64.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|x64.Build.0 = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|x86.ActiveCfg = Debug|Any CPU
|
||||
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|x86.Build.0 = Debug|Any CPU
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|arm.ActiveCfg = Debug|arm
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|arm.Build.0 = Debug|arm
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|arm64.ActiveCfg = Debug|arm64
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|arm64.Build.0 = Debug|arm64
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|armel.ActiveCfg = Debug|armel
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|armel.Build.0 = Debug|armel
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|x64.Build.0 = Debug|x64
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|x86.Build.0 = Debug|x86
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|Any CPU.ActiveCfg = Debug|arm64
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|Any CPU.Build.0 = Debug|arm64
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|arm.ActiveCfg = Debug|arm
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|arm.Build.0 = Debug|arm
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|arm64.ActiveCfg = Debug|arm64
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|arm64.Build.0 = Debug|arm64
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|armel.ActiveCfg = Debug|armel
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|armel.Build.0 = Debug|armel
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|x64.ActiveCfg = Debug|x64
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|x64.Build.0 = Debug|x64
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|x86.ActiveCfg = Debug|x86
|
||||
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|x86.Build.0 = Debug|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
263
external/corert/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs
vendored
Normal file
263
external/corert/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
// 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.Collections.Generic;
|
||||
|
||||
using Internal.TypeSystem;
|
||||
|
||||
using ILCompiler.Metadata;
|
||||
using ILCompiler.DependencyAnalysis;
|
||||
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
|
||||
namespace ILCompiler
|
||||
{
|
||||
/// <summary>
|
||||
/// A metadata manager that knows the full set of metadata ahead of time.
|
||||
/// </summary>
|
||||
public sealed class AnalysisBasedMetadataManager : GeneratingMetadataManager, ICompilationRootProvider
|
||||
{
|
||||
private readonly List<ModuleDesc> _modulesWithMetadata;
|
||||
|
||||
private readonly Dictionary<TypeDesc, MetadataCategory> _reflectableTypes = new Dictionary<TypeDesc, MetadataCategory>();
|
||||
private readonly Dictionary<MethodDesc, MetadataCategory> _reflectableMethods = new Dictionary<MethodDesc, MetadataCategory>();
|
||||
private readonly Dictionary<FieldDesc, MetadataCategory> _reflectableFields = new Dictionary<FieldDesc, MetadataCategory>();
|
||||
|
||||
public AnalysisBasedMetadataManager(
|
||||
ModuleDesc generatedAssembly,
|
||||
CompilerTypeSystemContext typeSystemContext,
|
||||
MetadataBlockingPolicy blockingPolicy,
|
||||
string logFile,
|
||||
StackTraceEmissionPolicy stackTracePolicy,
|
||||
IEnumerable<ModuleDesc> modulesWithMetadata,
|
||||
IEnumerable<ReflectableEntity<TypeDesc>> reflectableTypes,
|
||||
IEnumerable<ReflectableEntity<MethodDesc>> reflectableMethods,
|
||||
IEnumerable<ReflectableEntity<FieldDesc>> reflectableFields)
|
||||
: base(generatedAssembly, typeSystemContext, blockingPolicy, logFile, stackTracePolicy)
|
||||
{
|
||||
_modulesWithMetadata = new List<ModuleDesc>(modulesWithMetadata);
|
||||
|
||||
foreach (var refType in reflectableTypes)
|
||||
{
|
||||
_reflectableTypes.Add(refType.Entity, refType.Category);
|
||||
}
|
||||
|
||||
foreach (var refMethod in reflectableMethods)
|
||||
{
|
||||
// Asking for description or runtime mapping for a member without asking
|
||||
// for the owning type would mean we can't actually satisfy the request.
|
||||
Debug.Assert((refMethod.Category & MetadataCategory.Description) == 0
|
||||
|| (_reflectableTypes[refMethod.Entity.OwningType] & MetadataCategory.Description) != 0);
|
||||
Debug.Assert((refMethod.Category & MetadataCategory.RuntimeMapping) == 0
|
||||
|| (_reflectableTypes[refMethod.Entity.OwningType] & MetadataCategory.RuntimeMapping) != 0);
|
||||
_reflectableMethods.Add(refMethod.Entity, refMethod.Category);
|
||||
|
||||
MethodDesc canonMethod = refMethod.Entity.GetCanonMethodTarget(CanonicalFormKind.Specific);
|
||||
if (refMethod.Entity != canonMethod)
|
||||
{
|
||||
if (!_reflectableMethods.TryGetValue(canonMethod, out MetadataCategory category))
|
||||
category = 0;
|
||||
_reflectableMethods[canonMethod] = category | refMethod.Category;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var refField in reflectableFields)
|
||||
{
|
||||
// Asking for description or runtime mapping for a member without asking
|
||||
// for the owning type would mean we can't actually satisfy the request.
|
||||
Debug.Assert((refField.Category & MetadataCategory.Description) == 0
|
||||
|| (_reflectableTypes[refField.Entity.OwningType] & MetadataCategory.Description) != 0);
|
||||
Debug.Assert((refField.Category & MetadataCategory.RuntimeMapping) == 0
|
||||
|| (_reflectableTypes[refField.Entity.OwningType] & MetadataCategory.RuntimeMapping) != 0);
|
||||
_reflectableFields.Add(refField.Entity, refField.Category);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
HashSet<ModuleDesc> moduleHash = new HashSet<ModuleDesc>(_modulesWithMetadata);
|
||||
foreach (var refType in reflectableTypes)
|
||||
{
|
||||
// The instantiated types need to agree on the Description bit with the definition.
|
||||
// GetMetadataCategory relies on that.
|
||||
Debug.Assert((GetMetadataCategory(refType.Entity.GetTypeDefinition()) & MetadataCategory.Description)
|
||||
== (GetMetadataCategory(refType.Entity) & MetadataCategory.Description));
|
||||
|
||||
Debug.Assert(!(refType.Entity is MetadataType) || moduleHash.Contains(((MetadataType)refType.Entity).Module));
|
||||
}
|
||||
|
||||
foreach (var refMethod in reflectableMethods)
|
||||
{
|
||||
// The instantiated methods need to agree on the Description bit with the definition.
|
||||
// GetMetadataCategory relies on that.
|
||||
Debug.Assert((GetMetadataCategory(refMethod.Entity.GetTypicalMethodDefinition()) & MetadataCategory.Description)
|
||||
== (GetMetadataCategory(refMethod.Entity) & MetadataCategory.Description));
|
||||
}
|
||||
|
||||
foreach (var refField in reflectableFields)
|
||||
{
|
||||
// The instantiated fields need to agree on the Description bit with the definition.
|
||||
// GetMetadataCategory relies on that.
|
||||
Debug.Assert((GetMetadataCategory(refField.Entity.GetTypicalFieldDefinition()) & MetadataCategory.Description)
|
||||
== (GetMetadataCategory(refField.Entity) & MetadataCategory.Description));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override IEnumerable<ModuleDesc> GetCompilationModulesWithMetadata()
|
||||
{
|
||||
return _modulesWithMetadata;
|
||||
}
|
||||
|
||||
protected override void ComputeMetadata(NodeFactory factory,
|
||||
out byte[] metadataBlob,
|
||||
out List<MetadataMapping<MetadataType>> typeMappings,
|
||||
out List<MetadataMapping<MethodDesc>> methodMappings,
|
||||
out List<MetadataMapping<FieldDesc>> fieldMappings,
|
||||
out List<MetadataMapping<MethodDesc>> stackTraceMapping)
|
||||
{
|
||||
ComputeMetadata(new Policy(_blockingPolicy, this), factory,
|
||||
out metadataBlob,
|
||||
out typeMappings,
|
||||
out methodMappings,
|
||||
out fieldMappings,
|
||||
out stackTraceMapping);
|
||||
}
|
||||
|
||||
protected sealed override MetadataCategory GetMetadataCategory(MethodDesc method)
|
||||
{
|
||||
if (_reflectableMethods.TryGetValue(method, out MetadataCategory value))
|
||||
return value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected sealed override MetadataCategory GetMetadataCategory(TypeDesc type)
|
||||
{
|
||||
if (_reflectableTypes.TryGetValue(type, out MetadataCategory value))
|
||||
return value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected sealed override MetadataCategory GetMetadataCategory(FieldDesc field)
|
||||
{
|
||||
if (_reflectableFields.TryGetValue(field, out MetadataCategory value))
|
||||
return value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected override IEnumerable<FieldDesc> GetFieldsWithRuntimeMapping()
|
||||
{
|
||||
foreach (var pair in _reflectableFields)
|
||||
{
|
||||
if ((pair.Value & MetadataCategory.RuntimeMapping) != 0)
|
||||
yield return pair.Key;
|
||||
}
|
||||
}
|
||||
|
||||
void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider)
|
||||
{
|
||||
// We go over all the types and members that need a runtime artiface present in the
|
||||
// compiled executable and root it.
|
||||
|
||||
const string reason = "Reflection";
|
||||
|
||||
foreach (var pair in _reflectableTypes)
|
||||
{
|
||||
if ((pair.Value & MetadataCategory.RuntimeMapping) != 0)
|
||||
rootProvider.AddCompilationRoot(pair.Key, reason);
|
||||
}
|
||||
|
||||
foreach (var pair in _reflectableMethods)
|
||||
{
|
||||
if ((pair.Value & MetadataCategory.RuntimeMapping) != 0)
|
||||
{
|
||||
MethodDesc method = pair.Key;
|
||||
|
||||
// We need to root virtual methods as if they were called virtually.
|
||||
// This will possibly trigger the generation of other overrides too.
|
||||
if (method.IsVirtual)
|
||||
rootProvider.RootVirtualMethodForReflection(method, reason);
|
||||
|
||||
if (!method.IsAbstract)
|
||||
rootProvider.AddCompilationRoot(pair.Key, reason);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var pair in _reflectableFields)
|
||||
{
|
||||
if ((pair.Value & MetadataCategory.RuntimeMapping) != 0)
|
||||
{
|
||||
FieldDesc field = pair.Key;
|
||||
|
||||
// We only care about static fields at this point. Instance fields don't need
|
||||
// runtime artifacts generated in the image.
|
||||
if (field.IsStatic && !field.IsLiteral)
|
||||
{
|
||||
if (field.IsThreadStatic)
|
||||
rootProvider.RootThreadStaticBaseForType(field.OwningType, reason);
|
||||
else if (field.HasGCStaticBase)
|
||||
rootProvider.RootGCStaticBaseForType(field.OwningType, reason);
|
||||
else
|
||||
rootProvider.RootNonGCStaticBaseForType(field.OwningType, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct Policy : IMetadataPolicy
|
||||
{
|
||||
private readonly MetadataBlockingPolicy _blockingPolicy;
|
||||
private readonly ExplicitScopeAssemblyPolicyMixin _explicitScopeMixin;
|
||||
private readonly AnalysisBasedMetadataManager _parent;
|
||||
|
||||
public Policy(MetadataBlockingPolicy blockingPolicy,
|
||||
AnalysisBasedMetadataManager parent)
|
||||
{
|
||||
_blockingPolicy = blockingPolicy;
|
||||
_parent = parent;
|
||||
_explicitScopeMixin = new ExplicitScopeAssemblyPolicyMixin();
|
||||
}
|
||||
|
||||
public bool GeneratesMetadata(FieldDesc fieldDef)
|
||||
{
|
||||
return (_parent.GetMetadataCategory(fieldDef) & MetadataCategory.Description) != 0;
|
||||
}
|
||||
|
||||
public bool GeneratesMetadata(MethodDesc methodDef)
|
||||
{
|
||||
return (_parent.GetMetadataCategory(methodDef) & MetadataCategory.Description) != 0;
|
||||
}
|
||||
|
||||
public bool GeneratesMetadata(MetadataType typeDef)
|
||||
{
|
||||
return (_parent.GetMetadataCategory(typeDef) & MetadataCategory.Description) != 0;
|
||||
}
|
||||
|
||||
public bool IsBlocked(MetadataType typeDef)
|
||||
{
|
||||
return _blockingPolicy.IsBlocked(typeDef);
|
||||
}
|
||||
|
||||
public bool IsBlocked(MethodDesc methodDef)
|
||||
{
|
||||
return _blockingPolicy.IsBlocked(methodDef);
|
||||
}
|
||||
|
||||
public ModuleDesc GetModuleOfType(MetadataType typeDef)
|
||||
{
|
||||
return _explicitScopeMixin.GetModuleOfType(typeDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct ReflectableEntity<TEntity>
|
||||
{
|
||||
public readonly TEntity Entity;
|
||||
public readonly MetadataCategory Category;
|
||||
|
||||
public ReflectableEntity(TEntity entity, MetadataCategory category)
|
||||
{
|
||||
Entity = entity;
|
||||
Category = category;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,14 +19,21 @@ namespace ILCompiler
|
||||
/// </summary>
|
||||
public sealed class BlockedInternalsBlockingPolicy : MetadataBlockingPolicy
|
||||
{
|
||||
private enum ModuleBlockingMode
|
||||
{
|
||||
None,
|
||||
BlockedInternals,
|
||||
FullyBlocked,
|
||||
}
|
||||
|
||||
private class ModuleBlockingState
|
||||
{
|
||||
public ModuleDesc Module { get; }
|
||||
public bool HasBlockedInternals { get; }
|
||||
public ModuleBlockingState(ModuleDesc module, bool hasBlockedInternals)
|
||||
public ModuleBlockingMode BlockingMode { get; }
|
||||
public ModuleBlockingState(ModuleDesc module, ModuleBlockingMode mode)
|
||||
{
|
||||
Module = module;
|
||||
HasBlockedInternals = hasBlockedInternals;
|
||||
BlockingMode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +45,18 @@ namespace ILCompiler
|
||||
protected override bool CompareValueToValue(ModuleBlockingState value1, ModuleBlockingState value2) => Object.ReferenceEquals(value1.Module, value2.Module);
|
||||
protected override ModuleBlockingState CreateValueFromKey(ModuleDesc module)
|
||||
{
|
||||
bool moduleHasBlockingPolicy = module.GetType("System.Runtime.CompilerServices", "__BlockReflectionAttribute", false) != null;
|
||||
return new ModuleBlockingState(module, moduleHasBlockingPolicy);
|
||||
ModuleBlockingMode blockingMode = ModuleBlockingMode.None;
|
||||
|
||||
if (module.GetType("System.Runtime.CompilerServices", "__BlockAllReflectionAttribute", false) != null)
|
||||
{
|
||||
blockingMode = ModuleBlockingMode.FullyBlocked;
|
||||
}
|
||||
else if (module.GetType("System.Runtime.CompilerServices", "__BlockReflectionAttribute", false) != null)
|
||||
{
|
||||
blockingMode = ModuleBlockingMode.BlockedInternals;
|
||||
}
|
||||
|
||||
return new ModuleBlockingState(module, blockingMode);
|
||||
}
|
||||
}
|
||||
private BlockedModulesHashtable _blockedModules = new BlockedModulesHashtable();
|
||||
@@ -70,17 +87,17 @@ namespace ILCompiler
|
||||
protected override bool CompareValueToValue(BlockingState value1, BlockingState value2) => Object.ReferenceEquals(value1.Type, value2.Type);
|
||||
protected override BlockingState CreateValueFromKey(EcmaType type)
|
||||
{
|
||||
bool isBlocked = false;
|
||||
if (_blockedModules.GetOrCreateValue(type.EcmaModule).HasBlockedInternals)
|
||||
{
|
||||
isBlocked = ComputeIsBlocked(type);
|
||||
}
|
||||
|
||||
ModuleBlockingMode moduleBlockingMode = _blockedModules.GetOrCreateValue(type.EcmaModule).BlockingMode;
|
||||
bool isBlocked = ComputeIsBlocked(type, moduleBlockingMode);
|
||||
return new BlockingState(type, isBlocked);
|
||||
}
|
||||
|
||||
private bool ComputeIsBlocked(EcmaType type)
|
||||
private bool ComputeIsBlocked(EcmaType type, ModuleBlockingMode blockingMode)
|
||||
{
|
||||
// If no blocking is applied to the module, the type is not blocked
|
||||
if (blockingMode == ModuleBlockingMode.None)
|
||||
return false;
|
||||
|
||||
// <Module> type always gets metadata
|
||||
if (type.IsModuleType)
|
||||
return false;
|
||||
@@ -89,6 +106,10 @@ namespace ILCompiler
|
||||
if (type.Name == "SR")
|
||||
return false;
|
||||
|
||||
// We block everything else if the module is blocked
|
||||
if (blockingMode == ModuleBlockingMode.FullyBlocked)
|
||||
return true;
|
||||
|
||||
var typeDefinition = type.MetadataReader.GetTypeDefinition(type.Handle);
|
||||
DefType containingType = type.ContainingType;
|
||||
if (containingType == null)
|
||||
@@ -102,7 +123,7 @@ namespace ILCompiler
|
||||
{
|
||||
if ((typeDefinition.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic)
|
||||
{
|
||||
return ComputeIsBlocked((EcmaType)containingType);
|
||||
return ComputeIsBlocked((EcmaType)containingType, blockingMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -115,6 +136,21 @@ namespace ILCompiler
|
||||
}
|
||||
private BlockedTypeHashtable _blockedTypes;
|
||||
|
||||
private MetadataType _arrayOfTType;
|
||||
private MetadataType InitializeArrayOfTType(TypeSystemEntity contextEntity)
|
||||
{
|
||||
_arrayOfTType = contextEntity.Context.SystemModule.GetType("System", "Array`1");
|
||||
return _arrayOfTType;
|
||||
}
|
||||
private MetadataType GetArrayOfTType(TypeSystemEntity contextEntity)
|
||||
{
|
||||
if (_arrayOfTType != null)
|
||||
{
|
||||
return _arrayOfTType;
|
||||
}
|
||||
return InitializeArrayOfTType(contextEntity);
|
||||
}
|
||||
|
||||
public BlockedInternalsBlockingPolicy()
|
||||
{
|
||||
_blockedTypes = new BlockedTypeHashtable(_blockedModules);
|
||||
@@ -139,14 +175,28 @@ namespace ILCompiler
|
||||
if (ecmaMethod == null)
|
||||
return true;
|
||||
|
||||
ModuleBlockingMode moduleBlockingMode = _blockedModules.GetOrCreateValue(ecmaMethod.Module).BlockingMode;
|
||||
if (moduleBlockingMode == ModuleBlockingMode.None)
|
||||
return false;
|
||||
else if (moduleBlockingMode == ModuleBlockingMode.FullyBlocked)
|
||||
return true;
|
||||
|
||||
// We are blocking internal implementation details
|
||||
Debug.Assert(moduleBlockingMode == ModuleBlockingMode.BlockedInternals);
|
||||
|
||||
if (_blockedTypes.GetOrCreateValue((EcmaType)ecmaMethod.OwningType).IsBlocked)
|
||||
return true;
|
||||
|
||||
if (_blockedModules.GetOrCreateValue(ecmaMethod.Module).HasBlockedInternals)
|
||||
{
|
||||
if ((ecmaMethod.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
|
||||
return true;
|
||||
}
|
||||
if ((ecmaMethod.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
|
||||
return true;
|
||||
|
||||
// Methods on Array`1<T> are implementation details that implement the generic interfaces on
|
||||
// arrays. They should not generate metadata or be reflection invokable.
|
||||
// We could get rid of this special casing two ways:
|
||||
// * Make these method stop being regular EcmaMethods with Array<T> as their owning type, or
|
||||
// * Make these methods implement the interfaces explicitly (they would become private and naturally blocked)
|
||||
if (ecmaMethod.OwningType == GetArrayOfTType(ecmaMethod))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -159,14 +209,20 @@ namespace ILCompiler
|
||||
if (ecmaField == null)
|
||||
return true;
|
||||
|
||||
ModuleBlockingMode moduleBlockingMode = _blockedModules.GetOrCreateValue(ecmaField.Module).BlockingMode;
|
||||
if (moduleBlockingMode == ModuleBlockingMode.None)
|
||||
return false;
|
||||
else if (moduleBlockingMode == ModuleBlockingMode.FullyBlocked)
|
||||
return true;
|
||||
|
||||
// We are blocking internal implementation details
|
||||
Debug.Assert(moduleBlockingMode == ModuleBlockingMode.BlockedInternals);
|
||||
|
||||
if (_blockedTypes.GetOrCreateValue((EcmaType)ecmaField.OwningType).IsBlocked)
|
||||
return true;
|
||||
|
||||
if (_blockedModules.GetOrCreateValue(ecmaField.Module).HasBlockedInternals)
|
||||
{
|
||||
if ((ecmaField.Attributes & FieldAttributes.Public) != FieldAttributes.Public)
|
||||
return true;
|
||||
}
|
||||
if ((ecmaField.Attributes & FieldAttributes.Public) != FieldAttributes.Public)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
28
external/corert/src/ILCompiler.Compiler/src/Compiler/CodeGenerationFailedException.cs
vendored
Normal file
28
external/corert/src/ILCompiler.Compiler/src/Compiler/CodeGenerationFailedException.cs
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// 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.TypeSystem;
|
||||
|
||||
namespace ILCompiler
|
||||
{
|
||||
public class CodeGenerationFailedException : InternalCompilerErrorException
|
||||
{
|
||||
private const string MessageText = "Code generation failed";
|
||||
|
||||
public MethodDesc Method { get; }
|
||||
|
||||
public CodeGenerationFailedException(MethodDesc method)
|
||||
: this(method, null)
|
||||
{
|
||||
}
|
||||
|
||||
public CodeGenerationFailedException(MethodDesc method, Exception inner)
|
||||
: base(MessageText, inner)
|
||||
{
|
||||
Method = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
95
external/corert/src/ILCompiler.Compiler/src/Compiler/ComparerCompilationRootProvider.cs
vendored
Normal file
95
external/corert/src/ILCompiler.Compiler/src/Compiler/ComparerCompilationRootProvider.cs
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
// 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 Internal.TypeSystem;
|
||||
|
||||
namespace ILCompiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Compilation roots necessary to enable use of the jit intrinsic based Comparer<T>.Default and EqualityComparer<T>.Default implementations
|
||||
/// </summary>
|
||||
public class ComparerCompilationRootProvider : ICompilationRootProvider
|
||||
{
|
||||
TypeSystemContext _context;
|
||||
|
||||
public ComparerCompilationRootProvider(TypeSystemContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
private Instantiation GetUniformInstantiation(int numArgs, TypeDesc uniformInstanitationType)
|
||||
{
|
||||
TypeDesc[] args = new TypeDesc[numArgs];
|
||||
for (int i = 0; i < numArgs; i++)
|
||||
args[i] = uniformInstanitationType;
|
||||
return new Instantiation(args);
|
||||
}
|
||||
|
||||
private MethodDesc InstantiateMethodOverUniformType(MethodDesc method, TypeDesc uniformInstanitationType)
|
||||
{
|
||||
method = method.GetTypicalMethodDefinition();
|
||||
|
||||
Instantiation typeUniformInstantiation = GetUniformInstantiation(method.OwningType.Instantiation.Length, uniformInstanitationType);
|
||||
|
||||
DefType owningType;
|
||||
|
||||
if (typeUniformInstantiation.Length == 0)
|
||||
owningType = (DefType)method.OwningType;
|
||||
else
|
||||
owningType = ((MetadataType)method.OwningType).MakeInstantiatedType(typeUniformInstantiation);
|
||||
|
||||
Instantiation methodUniformInstantiation = GetUniformInstantiation(method.Instantiation.Length, uniformInstanitationType);
|
||||
|
||||
MethodDesc uninstantiatedMethod = owningType.FindMethodOnTypeWithMatchingTypicalMethod(method);
|
||||
|
||||
if (methodUniformInstantiation.Length == 0)
|
||||
return uninstantiatedMethod;
|
||||
else
|
||||
return uninstantiatedMethod.MakeInstantiatedMethod(methodUniformInstantiation);
|
||||
}
|
||||
|
||||
private void AddUniformInstantiationForMethod(IRootingServiceProvider rootProvider, MethodDesc method, TypeDesc uniformInstanitationType)
|
||||
{
|
||||
MethodDesc instantiatedMethod = InstantiateMethodOverUniformType(method, uniformInstanitationType);
|
||||
rootProvider.AddCompilationRoot(instantiatedMethod, "Adding uniform instantiation");
|
||||
}
|
||||
|
||||
private void AddCanonInstantiationsForMethod(IRootingServiceProvider rootProvider, MethodDesc method, bool normalCanonSupported)
|
||||
{
|
||||
if (_context.SupportsCanon && normalCanonSupported)
|
||||
AddUniformInstantiationForMethod(rootProvider, method, _context.CanonType);
|
||||
|
||||
if (_context.SupportsUniversalCanon)
|
||||
AddUniformInstantiationForMethod(rootProvider, method, _context.UniversalCanonType);
|
||||
}
|
||||
|
||||
private void AddCanonInstantiationsForMethod(IRootingServiceProvider rootProvider, MetadataType type, string methodName, bool normalCanonSupported)
|
||||
{
|
||||
MethodDesc method = type.GetMethod(methodName, null);
|
||||
AddCanonInstantiationsForMethod(rootProvider, method, normalCanonSupported);
|
||||
}
|
||||
|
||||
public void AddCompilationRoots(IRootingServiceProvider rootProvider)
|
||||
{
|
||||
ModuleDesc systemModule = ((MetadataType)_context.GetWellKnownType(WellKnownType.Object)).Module;
|
||||
|
||||
MetadataType equalityComparerType = systemModule.GetType("Internal.IntrinsicSupport", "EqualityComparerHelpers", false) as MetadataType;
|
||||
if (equalityComparerType != null)
|
||||
{
|
||||
AddCanonInstantiationsForMethod(rootProvider, equalityComparerType, "GetKnownGenericEquatableComparer", true);
|
||||
AddCanonInstantiationsForMethod(rootProvider, equalityComparerType, "GetKnownObjectEquatableComparer", true);
|
||||
AddCanonInstantiationsForMethod(rootProvider, equalityComparerType, "GetKnownNullableEquatableComparer", false);
|
||||
AddCanonInstantiationsForMethod(rootProvider, equalityComparerType, "GetKnownEnumEquatableComparer", false);
|
||||
}
|
||||
|
||||
MetadataType comparerType = systemModule.GetType("Internal.IntrinsicSupport", "ComparerHelpers", false) as MetadataType;
|
||||
if (comparerType != null)
|
||||
{
|
||||
AddCanonInstantiationsForMethod(rootProvider, comparerType, "GetKnownGenericComparer", true);
|
||||
AddCanonInstantiationsForMethod(rootProvider, comparerType, "GetKnownObjectComparer", true);
|
||||
AddCanonInstantiationsForMethod(rootProvider, comparerType, "GetKnownNullableComparer", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
|
||||
using ILCompiler.DependencyAnalysis;
|
||||
@@ -23,6 +24,8 @@ namespace ILCompiler
|
||||
protected readonly DependencyAnalyzerBase<NodeFactory> _dependencyGraph;
|
||||
protected readonly NodeFactory _nodeFactory;
|
||||
protected readonly Logger _logger;
|
||||
private readonly DebugInformationProvider _debugInformationProvider;
|
||||
private readonly DevirtualizationManager _devirtualizationManager;
|
||||
|
||||
public NameMangler NameMangler => _nodeFactory.NameMangler;
|
||||
public NodeFactory NodeFactory => _nodeFactory;
|
||||
@@ -30,8 +33,6 @@ namespace ILCompiler
|
||||
public Logger Logger => _logger;
|
||||
internal PInvokeILProvider PInvokeILProvider { get; }
|
||||
|
||||
protected abstract bool GenerateDebugInfo { get; }
|
||||
|
||||
private readonly TypeGetTypeMethodThunkCache _typeGetTypeMethodThunks;
|
||||
private readonly AssemblyGetExecutingAssemblyMethodThunkCache _assemblyGetExecutingAssemblyMethodThunks;
|
||||
private readonly MethodBaseGetCurrentMethodThunkCache _methodBaseGetCurrentMethodThunks;
|
||||
@@ -40,11 +41,15 @@ namespace ILCompiler
|
||||
DependencyAnalyzerBase<NodeFactory> dependencyGraph,
|
||||
NodeFactory nodeFactory,
|
||||
IEnumerable<ICompilationRootProvider> compilationRoots,
|
||||
DebugInformationProvider debugInformationProvider,
|
||||
DevirtualizationManager devirtualizationManager,
|
||||
Logger logger)
|
||||
{
|
||||
_dependencyGraph = dependencyGraph;
|
||||
_nodeFactory = nodeFactory;
|
||||
_logger = logger;
|
||||
_debugInformationProvider = debugInformationProvider;
|
||||
_devirtualizationManager = devirtualizationManager;
|
||||
|
||||
_dependencyGraph.ComputeDependencyRoutine += ComputeDependencyNodeDependencies;
|
||||
NodeFactory.AttachToDependencyGraph(_dependencyGraph);
|
||||
@@ -115,12 +120,7 @@ namespace ILCompiler
|
||||
|
||||
public MethodDebugInformation GetDebugInfo(MethodIL methodIL)
|
||||
{
|
||||
if (!GenerateDebugInfo)
|
||||
return MethodDebugInformation.None;
|
||||
|
||||
// This method looks odd right now, but it's an extensibility point that lets us generate
|
||||
// fake debugging information for things that don't have physical symbols.
|
||||
return methodIL.GetDebugInfo();
|
||||
return _debugInformationProvider.GetDebugInfo(methodIL);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -176,7 +176,142 @@ namespace ILCompiler
|
||||
return intrinsicMethod;
|
||||
}
|
||||
|
||||
void ICompilation.Compile(string outputFile, ObjectDumper dumper)
|
||||
public bool HasFixedSlotVTable(TypeDesc type)
|
||||
{
|
||||
return NodeFactory.VTable(type).HasFixedSlots;
|
||||
}
|
||||
|
||||
public bool IsEffectivelySealed(TypeDesc type)
|
||||
{
|
||||
return _devirtualizationManager.IsEffectivelySealed(type);
|
||||
}
|
||||
|
||||
public bool IsEffectivelySealed(MethodDesc method)
|
||||
{
|
||||
return _devirtualizationManager.IsEffectivelySealed(method);
|
||||
}
|
||||
|
||||
public MethodDesc ResolveVirtualMethod(MethodDesc declMethod, TypeDesc implType)
|
||||
{
|
||||
return _devirtualizationManager.ResolveVirtualMethod(declMethod, implType);
|
||||
}
|
||||
|
||||
public bool NeedsRuntimeLookup(ReadyToRunHelperId lookupKind, object targetOfLookup)
|
||||
{
|
||||
switch (lookupKind)
|
||||
{
|
||||
case ReadyToRunHelperId.TypeHandle:
|
||||
case ReadyToRunHelperId.NecessaryTypeHandle:
|
||||
case ReadyToRunHelperId.DefaultConstructor:
|
||||
return ((TypeDesc)targetOfLookup).IsRuntimeDeterminedSubtype;
|
||||
|
||||
case ReadyToRunHelperId.MethodDictionary:
|
||||
case ReadyToRunHelperId.MethodEntry:
|
||||
case ReadyToRunHelperId.VirtualDispatchCell:
|
||||
case ReadyToRunHelperId.MethodHandle:
|
||||
return ((MethodDesc)targetOfLookup).IsRuntimeDeterminedExactMethod;
|
||||
|
||||
case ReadyToRunHelperId.FieldHandle:
|
||||
return ((FieldDesc)targetOfLookup).OwningType.IsRuntimeDeterminedSubtype;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public ISymbolNode ComputeConstantLookup(ReadyToRunHelperId lookupKind, object targetOfLookup)
|
||||
{
|
||||
switch (lookupKind)
|
||||
{
|
||||
case ReadyToRunHelperId.TypeHandle:
|
||||
return NodeFactory.ConstructedTypeSymbol((TypeDesc)targetOfLookup);
|
||||
case ReadyToRunHelperId.NecessaryTypeHandle:
|
||||
return NodeFactory.NecessaryTypeSymbol((TypeDesc)targetOfLookup);
|
||||
case ReadyToRunHelperId.MethodDictionary:
|
||||
return NodeFactory.MethodGenericDictionary((MethodDesc)targetOfLookup);
|
||||
case ReadyToRunHelperId.MethodEntry:
|
||||
return NodeFactory.FatFunctionPointer((MethodDesc)targetOfLookup);
|
||||
case ReadyToRunHelperId.MethodHandle:
|
||||
return NodeFactory.RuntimeMethodHandle((MethodDesc)targetOfLookup);
|
||||
case ReadyToRunHelperId.FieldHandle:
|
||||
return NodeFactory.RuntimeFieldHandle((FieldDesc)targetOfLookup);
|
||||
case ReadyToRunHelperId.DefaultConstructor:
|
||||
{
|
||||
var type = (TypeDesc)targetOfLookup;
|
||||
MethodDesc ctor = type.GetDefaultConstructor();
|
||||
if (ctor == null)
|
||||
{
|
||||
MetadataType activatorType = TypeSystemContext.SystemModule.GetKnownType("System", "Activator");
|
||||
MetadataType classWithMissingCtor = activatorType.GetKnownNestedType("ClassWithMissingConstructor");
|
||||
ctor = classWithMissingCtor.GetParameterlessConstructor();
|
||||
}
|
||||
return NodeFactory.CanonicalEntrypoint(ctor);
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public GenericDictionaryLookup ComputeGenericLookup(MethodDesc contextMethod, ReadyToRunHelperId lookupKind, object targetOfLookup)
|
||||
{
|
||||
GenericContextSource contextSource;
|
||||
|
||||
if (contextMethod.RequiresInstMethodDescArg())
|
||||
{
|
||||
contextSource = GenericContextSource.MethodParameter;
|
||||
}
|
||||
else if (contextMethod.RequiresInstMethodTableArg())
|
||||
{
|
||||
contextSource = GenericContextSource.TypeParameter;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(contextMethod.AcquiresInstMethodTableFromThis());
|
||||
contextSource = GenericContextSource.ThisObject;
|
||||
}
|
||||
|
||||
// Can we do a fixed lookup? Start by checking if we can get to the dictionary.
|
||||
// Context source having a vtable with fixed slots is a prerequisite.
|
||||
if (contextSource == GenericContextSource.MethodParameter
|
||||
|| HasFixedSlotVTable(contextMethod.OwningType))
|
||||
{
|
||||
DictionaryLayoutNode dictionaryLayout;
|
||||
if (contextSource == GenericContextSource.MethodParameter)
|
||||
dictionaryLayout = _nodeFactory.GenericDictionaryLayout(contextMethod);
|
||||
else
|
||||
dictionaryLayout = _nodeFactory.GenericDictionaryLayout(contextMethod.OwningType);
|
||||
|
||||
// If the dictionary layout has fixed slots, we can compute the lookup now. Otherwise defer to helper.
|
||||
if (dictionaryLayout.HasFixedSlots)
|
||||
{
|
||||
int pointerSize = _nodeFactory.Target.PointerSize;
|
||||
|
||||
GenericLookupResult lookup = ReadyToRunGenericHelperNode.GetLookupSignature(_nodeFactory, lookupKind, targetOfLookup);
|
||||
int dictionarySlot = dictionaryLayout.GetSlotForFixedEntry(lookup);
|
||||
if (dictionarySlot != -1)
|
||||
{
|
||||
int dictionaryOffset = dictionarySlot * pointerSize;
|
||||
|
||||
if (contextSource == GenericContextSource.MethodParameter)
|
||||
{
|
||||
return GenericDictionaryLookup.CreateFixedLookup(contextSource, dictionaryOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
int vtableSlot = VirtualMethodSlotHelper.GetGenericDictionarySlot(_nodeFactory, contextMethod.OwningType);
|
||||
int vtableOffset = EETypeNode.GetVTableOffset(pointerSize) + vtableSlot * pointerSize;
|
||||
return GenericDictionaryLookup.CreateFixedLookup(contextSource, vtableOffset, dictionaryOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fixed lookup not possible - use helper.
|
||||
return GenericDictionaryLookup.CreateHelperLookup(contextSource);
|
||||
}
|
||||
|
||||
CompilationResults ICompilation.Compile(string outputFile, ObjectDumper dumper)
|
||||
{
|
||||
if (dumper != null)
|
||||
{
|
||||
@@ -191,15 +326,8 @@ namespace ILCompiler
|
||||
{
|
||||
dumper.End();
|
||||
}
|
||||
}
|
||||
|
||||
void ICompilation.WriteDependencyLog(string fileName)
|
||||
{
|
||||
using (FileStream dgmlOutput = new FileStream(fileName, FileMode.Create))
|
||||
{
|
||||
DgmlWriter.WriteDependencyGraphToStream(dgmlOutput, _dependencyGraph, _nodeFactory);
|
||||
dgmlOutput.Flush();
|
||||
}
|
||||
return new CompilationResults(_dependencyGraph, _nodeFactory);
|
||||
}
|
||||
|
||||
private class RootingServiceProvider : IRootingServiceProvider
|
||||
@@ -224,59 +352,130 @@ namespace ILCompiler
|
||||
|
||||
public void AddCompilationRoot(TypeDesc type, string reason)
|
||||
{
|
||||
if (!ConstructedEETypeNode.CreationAllowed(type))
|
||||
{
|
||||
_graph.AddRoot(_factory.NecessaryTypeSymbol(type), reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
_graph.AddRoot(_factory.ConstructedTypeSymbol(type), reason);
|
||||
}
|
||||
_graph.AddRoot(_factory.MaximallyConstructableType(type), reason);
|
||||
}
|
||||
|
||||
public void RootStaticBasesForType(TypeDesc type, string reason)
|
||||
public void RootThreadStaticBaseForType(TypeDesc type, string reason)
|
||||
{
|
||||
Debug.Assert(!type.IsGenericDefinition);
|
||||
|
||||
MetadataType metadataType = type as MetadataType;
|
||||
if (metadataType != null)
|
||||
if (metadataType != null && metadataType.ThreadStaticFieldSize.AsInt > 0)
|
||||
{
|
||||
if (metadataType.ThreadStaticFieldSize.AsInt > 0)
|
||||
{
|
||||
_graph.AddRoot(_factory.TypeThreadStaticIndex(metadataType), reason);
|
||||
}
|
||||
_graph.AddRoot(_factory.TypeThreadStaticIndex(metadataType), reason);
|
||||
|
||||
if (metadataType.GCStaticFieldSize.AsInt > 0)
|
||||
{
|
||||
_graph.AddRoot(_factory.TypeGCStaticsSymbol(metadataType), reason);
|
||||
}
|
||||
|
||||
if (metadataType.NonGCStaticFieldSize.AsInt > 0)
|
||||
{
|
||||
// Also explicitly root the non-gc base if we have a lazy cctor
|
||||
if(_factory.TypeSystemContext.HasLazyStaticConstructor(type))
|
||||
_graph.AddRoot(_factory.TypeNonGCStaticsSymbol(metadataType), reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void RootGCStaticBaseForType(TypeDesc type, string reason)
|
||||
{
|
||||
Debug.Assert(!type.IsGenericDefinition);
|
||||
|
||||
MetadataType metadataType = type as MetadataType;
|
||||
if (metadataType != null && metadataType.GCStaticFieldSize.AsInt > 0)
|
||||
{
|
||||
_graph.AddRoot(_factory.TypeGCStaticsSymbol(metadataType), reason);
|
||||
|
||||
// Also explicitly root the non-gc base if we have a lazy cctor
|
||||
if (_factory.TypeSystemContext.HasLazyStaticConstructor(type))
|
||||
_graph.AddRoot(_factory.TypeNonGCStaticsSymbol(metadataType), reason);
|
||||
}
|
||||
}
|
||||
|
||||
public void RootNonGCStaticBaseForType(TypeDesc type, string reason)
|
||||
{
|
||||
Debug.Assert(!type.IsGenericDefinition);
|
||||
|
||||
MetadataType metadataType = type as MetadataType;
|
||||
if (metadataType != null && (metadataType.NonGCStaticFieldSize.AsInt > 0 || _factory.TypeSystemContext.HasLazyStaticConstructor(type)))
|
||||
{
|
||||
_graph.AddRoot(_factory.TypeNonGCStaticsSymbol(metadataType), reason);
|
||||
}
|
||||
}
|
||||
|
||||
public void RootVirtualMethodForReflection(MethodDesc method, string reason)
|
||||
{
|
||||
Debug.Assert(method.IsVirtual);
|
||||
|
||||
if (!_factory.CompilationModuleGroup.ShouldProduceFullVTable(method.OwningType))
|
||||
_graph.AddRoot(_factory.VirtualMethodUse(method), reason);
|
||||
// Virtual method use is tracked on the slot defining method only.
|
||||
MethodDesc slotDefiningMethod = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method);
|
||||
if (!_factory.VTable(slotDefiningMethod.OwningType).HasFixedSlots)
|
||||
_graph.AddRoot(_factory.VirtualMethodUse(slotDefiningMethod), reason);
|
||||
|
||||
if (method.IsAbstract)
|
||||
{
|
||||
_graph.AddRoot(_factory.ReflectableMethod(method), reason);
|
||||
}
|
||||
}
|
||||
|
||||
public void RootModuleMetadata(ModuleDesc module, string reason)
|
||||
{
|
||||
_graph.AddRoot(_factory.ModuleMetadata(module), reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Interface under which Compilation is exposed externally.
|
||||
public interface ICompilation
|
||||
{
|
||||
void Compile(string outputFileName, ObjectDumper dumper);
|
||||
void WriteDependencyLog(string outputFileName);
|
||||
CompilationResults Compile(string outputFileName, ObjectDumper dumper);
|
||||
}
|
||||
|
||||
public class CompilationResults
|
||||
{
|
||||
private readonly DependencyAnalyzerBase<NodeFactory> _graph;
|
||||
private readonly NodeFactory _factory;
|
||||
|
||||
protected ImmutableArray<DependencyNodeCore<NodeFactory>> MarkedNodes
|
||||
{
|
||||
get
|
||||
{
|
||||
return _graph.MarkedNodeList;
|
||||
}
|
||||
}
|
||||
|
||||
internal CompilationResults(DependencyAnalyzerBase<NodeFactory> graph, NodeFactory factory)
|
||||
{
|
||||
_graph = graph;
|
||||
_factory = factory;
|
||||
}
|
||||
|
||||
public void WriteDependencyLog(string fileName)
|
||||
{
|
||||
using (FileStream dgmlOutput = new FileStream(fileName, FileMode.Create))
|
||||
{
|
||||
DgmlWriter.WriteDependencyGraphToStream(dgmlOutput, _graph, _factory);
|
||||
dgmlOutput.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<MethodDesc> CompiledMethodBodies
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var node in MarkedNodes)
|
||||
{
|
||||
if (node is IMethodBodyNode)
|
||||
yield return ((IMethodBodyNode)node).Method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<TypeDesc> ConstructedEETypes
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var node in MarkedNodes)
|
||||
{
|
||||
if (node is ConstructedEETypeNode || node is CanonicalEETypeNode)
|
||||
{
|
||||
yield return ((IEETypeNode)node).Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,15 +22,18 @@ namespace ILCompiler
|
||||
private DependencyTrackingLevel _dependencyTrackingLevel = DependencyTrackingLevel.None;
|
||||
protected IEnumerable<ICompilationRootProvider> _compilationRoots = Array.Empty<ICompilationRootProvider>();
|
||||
protected OptimizationMode _optimizationMode = OptimizationMode.None;
|
||||
protected bool _generateDebugInfo = false;
|
||||
protected MetadataManager _metadataManager;
|
||||
protected VTableSliceProvider _vtableSliceProvider = new LazyVTableSliceProvider();
|
||||
protected DictionaryLayoutProvider _dictionaryLayoutProvider = new LazyDictionaryLayoutProvider();
|
||||
protected DebugInformationProvider _debugInformationProvider = new DebugInformationProvider();
|
||||
protected DevirtualizationManager _devirtualizationManager = new DevirtualizationManager();
|
||||
|
||||
public CompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler nameMangler)
|
||||
{
|
||||
_context = context;
|
||||
_compilationGroup = compilationGroup;
|
||||
_nameMangler = nameMangler;
|
||||
_metadataManager = new EmptyMetadataManager(compilationGroup, context);
|
||||
_metadataManager = new EmptyMetadataManager(context);
|
||||
}
|
||||
|
||||
public CompilationBuilder UseLogger(Logger logger)
|
||||
@@ -63,18 +66,35 @@ namespace ILCompiler
|
||||
return this;
|
||||
}
|
||||
|
||||
public CompilationBuilder UseDebugInfo(bool generateDebugInfo)
|
||||
public CompilationBuilder UseVTableSliceProvider(VTableSliceProvider provider)
|
||||
{
|
||||
_generateDebugInfo = generateDebugInfo;
|
||||
_vtableSliceProvider = provider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CompilationBuilder UseGenericDictionaryLayoutProvider(DictionaryLayoutProvider provider)
|
||||
{
|
||||
_dictionaryLayoutProvider = provider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CompilationBuilder UseDevirtualizationManager(DevirtualizationManager manager)
|
||||
{
|
||||
_devirtualizationManager = manager;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CompilationBuilder UseDebugInfoProvider(DebugInformationProvider provider)
|
||||
{
|
||||
_debugInformationProvider = provider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public abstract CompilationBuilder UseBackendOptions(IEnumerable<string> options);
|
||||
|
||||
protected DependencyAnalyzerBase<NodeFactory> CreateDependencyGraph(NodeFactory factory)
|
||||
protected DependencyAnalyzerBase<NodeFactory> CreateDependencyGraph(NodeFactory factory, IComparer<DependencyNodeCore<NodeFactory>> comparer = null)
|
||||
{
|
||||
// TODO: add graph sorter when we go multi-threaded
|
||||
return _dependencyTrackingLevel.CreateDependencyGraph(factory);
|
||||
return _dependencyTrackingLevel.CreateDependencyGraph(factory, comparer);
|
||||
}
|
||||
|
||||
public ILScannerBuilder GetILScannerBuilder(CompilationModuleGroup compilationGroup = null)
|
||||
|
||||
@@ -12,6 +12,13 @@ using Debug = System.Diagnostics.Debug;
|
||||
|
||||
namespace ILCompiler
|
||||
{
|
||||
public enum ExportForm
|
||||
{
|
||||
None = 0,
|
||||
ByName = 1,
|
||||
ByOrdinal = 2,
|
||||
}
|
||||
|
||||
public abstract class CompilationModuleGroup
|
||||
{
|
||||
/// <summary>
|
||||
@@ -30,9 +37,13 @@ namespace ILCompiler
|
||||
/// </summary>
|
||||
public abstract bool ContainsType(TypeDesc type);
|
||||
/// <summary>
|
||||
/// If true, type dictionary of "type" is in the module to be compiled
|
||||
/// </summary>
|
||||
public abstract bool ContainsTypeDictionary(TypeDesc type);
|
||||
/// <summary>
|
||||
/// If true, "method" is in the set of input assemblies being compiled
|
||||
/// </summary>
|
||||
public abstract bool ContainsMethodBody(MethodDesc method);
|
||||
public abstract bool ContainsMethodBody(MethodDesc method, bool unboxingStub);
|
||||
/// <summary>
|
||||
/// If true, the generic dictionary of "method" is in the set of input assemblies being compiled
|
||||
/// </summary>
|
||||
@@ -40,15 +51,19 @@ namespace ILCompiler
|
||||
/// <summary>
|
||||
/// If true, "type" is exported by the set of input assemblies being compiled
|
||||
/// </summary>
|
||||
public abstract bool ExportsType(TypeDesc type);
|
||||
public abstract ExportForm GetExportTypeForm(TypeDesc type);
|
||||
/// <summary>
|
||||
/// If true, generic dictionary of "type" is exported by the set of input assemblies being compiled
|
||||
/// </summary>
|
||||
public abstract ExportForm GetExportTypeFormDictionary(TypeDesc type);
|
||||
/// <summary>
|
||||
/// If true, "method" is exported by the set of input assemblies being compiled
|
||||
/// </summary>
|
||||
public abstract bool ExportsMethod(MethodDesc method);
|
||||
public abstract ExportForm GetExportMethodForm(MethodDesc method, bool unboxingStub);
|
||||
/// <summary>
|
||||
/// If true, the generic dictionary of "method" is exported by the set of input assemblies being compiled
|
||||
/// </summary>
|
||||
public abstract bool ExportsMethodDictionary(MethodDesc method);
|
||||
public abstract ExportForm GetExportMethodDictionaryForm(MethodDesc method);
|
||||
/// <summary>
|
||||
/// If true, all code is compiled into a single module
|
||||
/// </summary>
|
||||
@@ -64,6 +79,11 @@ namespace ILCompiler
|
||||
/// </summary>
|
||||
public abstract bool ShouldPromoteToFullType(TypeDesc type);
|
||||
/// <summary>
|
||||
/// If true, if a type is in the dependency graph, its non-generic methods that can be transformed
|
||||
/// into code must be.
|
||||
/// </summary>
|
||||
public abstract bool PresenceOfEETypeImpliesAllMethodsOnType(TypeDesc type);
|
||||
/// <summary>
|
||||
/// If true, the type will not be linked into the same module as the current compilation and therefore
|
||||
/// accessed through the target platform's import mechanism (ie, Import Address Table on Windows)
|
||||
/// </summary>
|
||||
@@ -102,10 +122,10 @@ namespace ILCompiler
|
||||
|
||||
public override MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true)
|
||||
{
|
||||
Debug.Assert(false, "Resolving a TypeRef in the compiler generated assembly?");
|
||||
Debug.Fail("Resolving a TypeRef in the compiler generated assembly?");
|
||||
|
||||
if (throwIfNotFound)
|
||||
throw new TypeSystemException.TypeLoadException(nameSpace, name, this);
|
||||
ThrowHelper.ThrowTypeLoadException(nameSpace, name, this);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
282
external/corert/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedInteropStubManager.cs
vendored
Normal file
282
external/corert/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedInteropStubManager.cs
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
// 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 System.Collections.Generic;
|
||||
|
||||
using Internal.IL.Stubs;
|
||||
using Internal.TypeSystem;
|
||||
using Internal.TypeSystem.Interop;
|
||||
using ILCompiler.DependencyAnalysis;
|
||||
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyList;
|
||||
using ReflectionMapBlob = Internal.Runtime.ReflectionMapBlob;
|
||||
|
||||
namespace ILCompiler
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is responsible for managing stub methods for interop
|
||||
/// </summary>
|
||||
public sealed class CompilerGeneratedInteropStubManager : InteropStubManager
|
||||
{
|
||||
internal HashSet<TypeDesc> _delegateMarshalingTypes = new HashSet<TypeDesc>();
|
||||
private HashSet<TypeDesc> _structMarshallingTypes = new HashSet<TypeDesc>();
|
||||
|
||||
public CompilerGeneratedInteropStubManager(CompilationModuleGroup compilationModuleGroup, CompilerTypeSystemContext typeSystemContext, InteropStateManager interopStateManager) :
|
||||
base(compilationModuleGroup, typeSystemContext, interopStateManager)
|
||||
{
|
||||
}
|
||||
|
||||
private MethodDesc GetOpenStaticDelegateMarshallingStub(TypeDesc delegateType)
|
||||
{
|
||||
var stub = InteropStateManager.GetOpenStaticDelegateMarshallingThunk(delegateType);
|
||||
Debug.Assert(stub != null);
|
||||
|
||||
_delegateMarshalingTypes.Add(delegateType);
|
||||
return stub;
|
||||
}
|
||||
|
||||
private MethodDesc GetClosedDelegateMarshallingStub(TypeDesc delegateType)
|
||||
{
|
||||
var stub = InteropStateManager.GetClosedDelegateMarshallingThunk(delegateType);
|
||||
Debug.Assert(stub != null);
|
||||
|
||||
_delegateMarshalingTypes.Add(delegateType);
|
||||
return stub;
|
||||
}
|
||||
private MethodDesc GetForwardDelegateCreationStub(TypeDesc delegateType)
|
||||
{
|
||||
var stub = InteropStateManager.GetForwardDelegateCreationThunk(delegateType);
|
||||
Debug.Assert(stub != null);
|
||||
|
||||
_delegateMarshalingTypes.Add(delegateType);
|
||||
return stub;
|
||||
}
|
||||
|
||||
private MethodDesc GetStructMarshallingManagedToNativeStub(TypeDesc structType)
|
||||
{
|
||||
MethodDesc stub = InteropStateManager.GetStructMarshallingManagedToNativeThunk(structType);
|
||||
Debug.Assert(stub != null);
|
||||
|
||||
_structMarshallingTypes.Add(structType);
|
||||
return stub;
|
||||
}
|
||||
|
||||
private MethodDesc GetStructMarshallingNativeToManagedStub(TypeDesc structType)
|
||||
{
|
||||
MethodDesc stub = InteropStateManager.GetStructMarshallingNativeToManagedThunk(structType);
|
||||
Debug.Assert(stub != null);
|
||||
|
||||
_structMarshallingTypes.Add(structType);
|
||||
return stub;
|
||||
}
|
||||
|
||||
private MethodDesc GetStructMarshallingCleanupStub(TypeDesc structType)
|
||||
{
|
||||
MethodDesc stub = InteropStateManager.GetStructMarshallingCleanupThunk(structType);
|
||||
Debug.Assert(stub != null);
|
||||
|
||||
_structMarshallingTypes.Add(structType);
|
||||
return stub;
|
||||
}
|
||||
|
||||
private TypeDesc GetInlineArrayType(InlineArrayCandidate candidate)
|
||||
{
|
||||
TypeDesc inlineArrayType = InteropStateManager.GetInlineArrayType(candidate);
|
||||
Debug.Assert(inlineArrayType != null);
|
||||
return inlineArrayType;
|
||||
}
|
||||
|
||||
internal struct DelegateMarshallingThunks
|
||||
{
|
||||
public TypeDesc DelegateType;
|
||||
public MethodDesc OpenStaticDelegateMarshallingThunk;
|
||||
public MethodDesc ClosedDelegateMarshallingThunk;
|
||||
public MethodDesc DelegateCreationThunk;
|
||||
}
|
||||
|
||||
internal IEnumerable<DelegateMarshallingThunks> GetDelegateMarshallingThunks()
|
||||
{
|
||||
foreach (var delegateType in _delegateMarshalingTypes)
|
||||
{
|
||||
yield return
|
||||
new DelegateMarshallingThunks()
|
||||
{
|
||||
DelegateType = delegateType,
|
||||
OpenStaticDelegateMarshallingThunk = InteropStateManager.GetOpenStaticDelegateMarshallingThunk(delegateType),
|
||||
ClosedDelegateMarshallingThunk = InteropStateManager.GetClosedDelegateMarshallingThunk(delegateType),
|
||||
DelegateCreationThunk = InteropStateManager.GetForwardDelegateCreationThunk(delegateType)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal struct StructMarshallingThunks
|
||||
{
|
||||
public TypeDesc StructType;
|
||||
public NativeStructType NativeStructType;
|
||||
public MethodDesc MarshallingThunk;
|
||||
public MethodDesc UnmarshallingThunk;
|
||||
public MethodDesc CleanupThunk;
|
||||
}
|
||||
|
||||
internal IEnumerable<StructMarshallingThunks> GetStructMarshallingTypes()
|
||||
{
|
||||
foreach (var structType in _structMarshallingTypes)
|
||||
{
|
||||
yield return
|
||||
new StructMarshallingThunks()
|
||||
{
|
||||
StructType = structType,
|
||||
NativeStructType = InteropStateManager.GetStructMarshallingNativeType(structType),
|
||||
MarshallingThunk = InteropStateManager.GetStructMarshallingManagedToNativeThunk(structType),
|
||||
UnmarshallingThunk = InteropStateManager.GetStructMarshallingNativeToManagedThunk(structType),
|
||||
CleanupThunk = InteropStateManager.GetStructMarshallingCleanupThunk(structType)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void AddDependenciesDueToPInvokeStructDelegateField(ref DependencyList dependencies, NodeFactory factory, TypeDesc typeDesc)
|
||||
{
|
||||
if (typeDesc is ByRefType)
|
||||
{
|
||||
typeDesc = typeDesc.GetParameterType();
|
||||
}
|
||||
|
||||
MetadataType metadataType = typeDesc as MetadataType;
|
||||
if (metadataType != null)
|
||||
{
|
||||
foreach (FieldDesc field in metadataType.GetFields())
|
||||
{
|
||||
if (field.IsStatic)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
TypeDesc fieldType = field.FieldType;
|
||||
|
||||
if (fieldType.IsDelegate)
|
||||
{
|
||||
AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, fieldType);
|
||||
}
|
||||
else if (MarshalHelpers.IsStructMarshallingRequired(fieldType))
|
||||
{
|
||||
AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, fieldType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddDependeciesDueToPInvoke(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
|
||||
{
|
||||
if (method.IsPInvoke)
|
||||
{
|
||||
dependencies = dependencies ?? new DependencyList();
|
||||
|
||||
MethodSignature methodSig = method.Signature;
|
||||
AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, methodSig.ReturnType);
|
||||
|
||||
// struct may contain delegate fields, hence we need to add dependencies for it
|
||||
if (MarshalHelpers.IsStructMarshallingRequired(methodSig.ReturnType))
|
||||
{
|
||||
AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, methodSig.ReturnType);
|
||||
}
|
||||
|
||||
for (int i = 0; i < methodSig.Length; i++)
|
||||
{
|
||||
AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, methodSig[i]);
|
||||
if (MarshalHelpers.IsStructMarshallingRequired(methodSig[i]))
|
||||
{
|
||||
AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, methodSig[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (method.HasInstantiation)
|
||||
{
|
||||
dependencies = dependencies ?? new DependencyList();
|
||||
AddMarshalAPIsGenericDependencies(ref dependencies, factory, method);
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddInterestingInteropConstructedTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
|
||||
{
|
||||
if (type.IsDelegate)
|
||||
{
|
||||
var delegateType = (MetadataType)type;
|
||||
if (delegateType.HasCustomAttribute("System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute"))
|
||||
{
|
||||
AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, delegateType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For Marshal generic APIs(eg. Marshal.StructureToPtr<T>, GetFunctionPointerForDelegate) we add
|
||||
/// the generic parameter as dependencies so that we can generate runtime data for them
|
||||
/// </summary>
|
||||
public override void AddMarshalAPIsGenericDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
|
||||
{
|
||||
Debug.Assert(method.HasInstantiation);
|
||||
|
||||
TypeDesc owningType = method.OwningType;
|
||||
MetadataType metadataType = owningType as MetadataType;
|
||||
if (metadataType != null && metadataType.Module == _interopModule)
|
||||
{
|
||||
if (metadataType.Name == "Marshal" && metadataType.Namespace == "System.Runtime.InteropServices")
|
||||
{
|
||||
string methodName = method.Name;
|
||||
if (methodName == "GetFunctionPointerForDelegate" ||
|
||||
methodName == "GetDelegateForFunctionPointer" ||
|
||||
methodName == "PtrToStructure" ||
|
||||
methodName == "StructureToPtr" ||
|
||||
methodName == "SizeOf" ||
|
||||
methodName == "OffsetOf")
|
||||
{
|
||||
foreach (TypeDesc type in method.Instantiation)
|
||||
{
|
||||
AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, type);
|
||||
AddDependenciesDueToPInvokeStruct(ref dependencies, factory, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddDependenciesDueToPInvokeDelegate(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
|
||||
{
|
||||
if (type.IsDelegate)
|
||||
{
|
||||
dependencies.Add(factory.NecessaryTypeSymbol(type), "Delegate Marshalling Stub");
|
||||
|
||||
dependencies.Add(factory.MethodEntrypoint(GetOpenStaticDelegateMarshallingStub(type)), "Delegate Marshalling Stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(GetClosedDelegateMarshallingStub(type)), "Delegate Marshalling Stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(GetForwardDelegateCreationStub(type)), "Delegate Marshalling Stub");
|
||||
}
|
||||
}
|
||||
|
||||
private void AddDependenciesDueToPInvokeStruct(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
|
||||
{
|
||||
if (MarshalHelpers.IsStructMarshallingRequired(type))
|
||||
{
|
||||
dependencies.Add(factory.NecessaryTypeSymbol(type), "Struct Marshalling Stub");
|
||||
|
||||
var stub = (StructMarshallingThunk)GetStructMarshallingManagedToNativeStub(type);
|
||||
dependencies.Add(factory.MethodEntrypoint(stub), "Struct Marshalling stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(GetStructMarshallingNativeToManagedStub(type)), "Struct Marshalling stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(GetStructMarshallingCleanupStub(type)), "Struct Marshalling stub");
|
||||
|
||||
AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, type);
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddToReadyToRunHeader(ReadyToRunHeaderNode header, NodeFactory nodeFactory, ExternalReferencesTableNode commonFixupsTableNode)
|
||||
{
|
||||
var delegateMapNode = new DelegateMarshallingStubMapNode(commonFixupsTableNode);
|
||||
header.Add(MetadataManager.BlobIdToReadyToRunSection(ReflectionMapBlob.DelegateMarshallingStubMap), delegateMapNode, delegateMapNode, delegateMapNode.EndSymbol);
|
||||
|
||||
var structMapNode = new StructMarshallingStubMapNode(commonFixupsTableNode);
|
||||
header.Add(MetadataManager.BlobIdToReadyToRunSection(ReflectionMapBlob.StructMarshallingStubMap), structMapNode, structMapNode, structMapNode.EndSymbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,284 +0,0 @@
|
||||
// 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 System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using Internal.IL.Stubs;
|
||||
using Internal.TypeSystem;
|
||||
using Internal.Metadata.NativeFormat.Writer;
|
||||
|
||||
using ILCompiler.Metadata;
|
||||
using ILCompiler.DependencyAnalysis;
|
||||
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyList;
|
||||
|
||||
namespace ILCompiler
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is responsible for managing native metadata to be emitted into the compiled
|
||||
/// module. It applies a policy that every type/method emitted shall be reflectable.
|
||||
/// </summary>
|
||||
public sealed class CompilerGeneratedMetadataManager : MetadataManager
|
||||
{
|
||||
private readonly string _metadataLogFile;
|
||||
private Dictionary<DynamicInvokeMethodSignature, MethodDesc> _dynamicInvokeThunks;
|
||||
|
||||
public CompilerGeneratedMetadataManager(CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext, string logFile)
|
||||
: base(group, typeSystemContext, new BlockedInternalsBlockingPolicy())
|
||||
{
|
||||
_metadataLogFile = logFile;
|
||||
|
||||
if (DynamicInvokeMethodThunk.SupportsThunks(typeSystemContext))
|
||||
{
|
||||
_dynamicInvokeThunks = new Dictionary<DynamicInvokeMethodSignature, MethodDesc>();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool WillUseMetadataTokenToReferenceMethod(MethodDesc method)
|
||||
{
|
||||
return (GetMetadataCategory(method) & MetadataCategory.Description) != 0;
|
||||
}
|
||||
|
||||
public override bool WillUseMetadataTokenToReferenceField(FieldDesc field)
|
||||
{
|
||||
return (GetMetadataCategory(field) & MetadataCategory.Description) != 0;
|
||||
}
|
||||
|
||||
protected override MetadataCategory GetMetadataCategory(FieldDesc field)
|
||||
{
|
||||
MetadataCategory category = 0;
|
||||
|
||||
if (!IsReflectionBlocked(field))
|
||||
{
|
||||
category = MetadataCategory.RuntimeMapping;
|
||||
|
||||
if (_compilationModuleGroup.ContainsType(field.GetTypicalFieldDefinition().OwningType))
|
||||
category |= MetadataCategory.Description;
|
||||
}
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
protected override MetadataCategory GetMetadataCategory(MethodDesc method)
|
||||
{
|
||||
MetadataCategory category = 0;
|
||||
|
||||
if (!IsReflectionBlocked(method))
|
||||
{
|
||||
category = MetadataCategory.RuntimeMapping;
|
||||
|
||||
if (_compilationModuleGroup.ContainsType(method.GetTypicalMethodDefinition().OwningType))
|
||||
category |= MetadataCategory.Description;
|
||||
}
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
protected override MetadataCategory GetMetadataCategory(TypeDesc type)
|
||||
{
|
||||
MetadataCategory category = 0;
|
||||
|
||||
if (!IsReflectionBlocked(type))
|
||||
{
|
||||
category = MetadataCategory.RuntimeMapping;
|
||||
|
||||
if (_compilationModuleGroup.ContainsType(type.GetTypeDefinition()))
|
||||
category |= MetadataCategory.Description;
|
||||
}
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
protected override void ComputeMetadata(NodeFactory factory,
|
||||
out byte[] metadataBlob,
|
||||
out List<MetadataMapping<MetadataType>> typeMappings,
|
||||
out List<MetadataMapping<MethodDesc>> methodMappings,
|
||||
out List<MetadataMapping<FieldDesc>> fieldMappings)
|
||||
{
|
||||
var transformed = MetadataTransform.Run(new GeneratedTypesAndCodeMetadataPolicy(_blockingPolicy, factory), GetCompilationModulesWithMetadata());
|
||||
|
||||
// TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate
|
||||
// TypeReference records for _typeDefinitionsGenerated that don't have metadata.
|
||||
// (To be used in MissingMetadataException messages)
|
||||
|
||||
// Generate metadata blob
|
||||
var writer = new MetadataWriter();
|
||||
writer.ScopeDefinitions.AddRange(transformed.Scopes);
|
||||
var ms = new MemoryStream();
|
||||
|
||||
// .NET metadata is UTF-16 and UTF-16 contains code points that don't translate to UTF-8.
|
||||
var noThrowUtf8Encoding = new UTF8Encoding(false, false);
|
||||
|
||||
using (var logWriter = _metadataLogFile != null ? new StreamWriter(File.Open(_metadataLogFile, FileMode.Create, FileAccess.Write, FileShare.Read), noThrowUtf8Encoding) : null)
|
||||
{
|
||||
writer.LogWriter = logWriter;
|
||||
writer.Write(ms);
|
||||
}
|
||||
|
||||
metadataBlob = ms.ToArray();
|
||||
|
||||
typeMappings = new List<MetadataMapping<MetadataType>>();
|
||||
methodMappings = new List<MetadataMapping<MethodDesc>>();
|
||||
fieldMappings = new List<MetadataMapping<FieldDesc>>();
|
||||
|
||||
// Generate type definition mappings
|
||||
foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
|
||||
{
|
||||
MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null;
|
||||
if (definition == null)
|
||||
continue;
|
||||
|
||||
MetadataRecord record = transformed.GetTransformedTypeDefinition(definition);
|
||||
|
||||
// Reflection requires that we maintain type identity. Even if we only generated a TypeReference record,
|
||||
// if there is an EEType for it, we also need a mapping table entry for it.
|
||||
if (record == null)
|
||||
record = transformed.GetTransformedTypeReference(definition);
|
||||
|
||||
if (record != null)
|
||||
typeMappings.Add(new MetadataMapping<MetadataType>(definition, writer.GetRecordHandle(record)));
|
||||
}
|
||||
|
||||
foreach (var method in GetCompiledMethods())
|
||||
{
|
||||
if (method.IsCanonicalMethod(CanonicalFormKind.Specific))
|
||||
{
|
||||
// Canonical methods are not interesting.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsReflectionBlocked(method.Instantiation) || IsReflectionBlocked(method.OwningType.Instantiation))
|
||||
continue;
|
||||
|
||||
MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition());
|
||||
|
||||
if (record != null)
|
||||
methodMappings.Add(new MetadataMapping<MethodDesc>(method, writer.GetRecordHandle(record)));
|
||||
}
|
||||
|
||||
foreach (var eetypeGenerated in GetTypesWithEETypes())
|
||||
{
|
||||
if (eetypeGenerated.IsGenericDefinition)
|
||||
continue;
|
||||
|
||||
if (eetypeGenerated.HasInstantiation)
|
||||
{
|
||||
// Collapsing of field map entries based on canonicalization, to avoid redundant equivalent entries
|
||||
|
||||
TypeDesc canonicalType = eetypeGenerated.ConvertToCanonForm(CanonicalFormKind.Specific);
|
||||
if (canonicalType != eetypeGenerated && TypeGeneratesEEType(canonicalType))
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (FieldDesc field in eetypeGenerated.GetFields())
|
||||
{
|
||||
if (IsReflectionBlocked(field.OwningType.Instantiation))
|
||||
continue;
|
||||
|
||||
Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition());
|
||||
if (record != null)
|
||||
fieldMappings.Add(new MetadataMapping<FieldDesc>(field, writer.GetRecordHandle(record)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is there a reflection invoke stub for a method that is invokable?
|
||||
/// </summary>
|
||||
public override bool HasReflectionInvokeStubForInvokableMethod(MethodDesc method)
|
||||
{
|
||||
Debug.Assert(IsReflectionInvokable(method));
|
||||
|
||||
if (_dynamicInvokeThunks == null)
|
||||
return false;
|
||||
|
||||
// Place an upper limit on how many parameters a method can have to still get a static stub.
|
||||
// From the past experience, methods taking 8000+ parameters get a stub that can hit various limitations
|
||||
// in the codegen. On Project N, we were limited to 256 parameters because of MDIL limitations.
|
||||
// We don't have such limitations here, but it's a nice round number.
|
||||
// Reflection invoke will still work, but will go through the calling convention converter.
|
||||
|
||||
return method.Signature.Length <= 256;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a stub that can be used to reflection-invoke a method with a given signature.
|
||||
/// </summary>
|
||||
public override MethodDesc GetCanonicalReflectionInvokeStub(MethodDesc method)
|
||||
{
|
||||
TypeSystemContext context = method.Context;
|
||||
var sig = method.Signature;
|
||||
|
||||
// Get a generic method that can be used to invoke method with this shape.
|
||||
MethodDesc thunk;
|
||||
var lookupSig = new DynamicInvokeMethodSignature(sig);
|
||||
if (!_dynamicInvokeThunks.TryGetValue(lookupSig, out thunk))
|
||||
{
|
||||
thunk = new DynamicInvokeMethodThunk(_compilationModuleGroup.GeneratedAssembly.GetGlobalModuleType(), lookupSig);
|
||||
_dynamicInvokeThunks.Add(lookupSig, thunk);
|
||||
}
|
||||
|
||||
return InstantiateCanonicalDynamicInvokeMethodForMethod(thunk, method);
|
||||
}
|
||||
|
||||
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
|
||||
{
|
||||
dependencies = dependencies ?? new DependencyList();
|
||||
dependencies.Add(factory.MethodMetadata(method.GetTypicalMethodDefinition()), "Reflectable method");
|
||||
}
|
||||
|
||||
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
|
||||
{
|
||||
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");
|
||||
}
|
||||
|
||||
private struct GeneratedTypesAndCodeMetadataPolicy : IMetadataPolicy
|
||||
{
|
||||
private readonly MetadataBlockingPolicy _blockingPolicy;
|
||||
private readonly NodeFactory _factory;
|
||||
private readonly ExplicitScopeAssemblyPolicyMixin _explicitScopeMixin;
|
||||
|
||||
public GeneratedTypesAndCodeMetadataPolicy(MetadataBlockingPolicy blockingPolicy, NodeFactory factory)
|
||||
{
|
||||
_blockingPolicy = blockingPolicy;
|
||||
_factory = factory;
|
||||
_explicitScopeMixin = new ExplicitScopeAssemblyPolicyMixin();
|
||||
}
|
||||
|
||||
public bool GeneratesMetadata(FieldDesc fieldDef)
|
||||
{
|
||||
return _factory.FieldMetadata(fieldDef).Marked;
|
||||
}
|
||||
|
||||
public bool GeneratesMetadata(MethodDesc methodDef)
|
||||
{
|
||||
return _factory.MethodMetadata(methodDef).Marked;
|
||||
}
|
||||
|
||||
public bool GeneratesMetadata(MetadataType typeDef)
|
||||
{
|
||||
return _factory.TypeMetadata(typeDef).Marked;
|
||||
}
|
||||
|
||||
public bool IsBlocked(MetadataType typeDef)
|
||||
{
|
||||
return _blockingPolicy.IsBlocked(typeDef);
|
||||
}
|
||||
|
||||
public bool IsBlocked(MethodDesc methodDef)
|
||||
{
|
||||
return _blockingPolicy.IsBlocked(methodDef);
|
||||
}
|
||||
|
||||
public ModuleDesc GetModuleOfType(MetadataType typeDef)
|
||||
{
|
||||
return _explicitScopeMixin.GetModuleOfType(typeDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,8 @@ namespace ILCompiler
|
||||
return TypeFlags.Class |
|
||||
TypeFlags.HasGenericVarianceComputed |
|
||||
TypeFlags.HasStaticConstructorComputed |
|
||||
TypeFlags.HasFinalizerComputed;
|
||||
TypeFlags.HasFinalizerComputed |
|
||||
TypeFlags.IsByRefLikeComputed;
|
||||
}
|
||||
|
||||
public override ClassLayoutMetadata GetClassLayout()
|
||||
|
||||
@@ -89,6 +89,40 @@ namespace ILCompiler
|
||||
return thunk;
|
||||
}
|
||||
|
||||
public MethodDesc GetUnboxingThunk(MethodDesc targetMethod, ModuleDesc ownerModuleOfThunk)
|
||||
{
|
||||
TypeDesc owningType = targetMethod.OwningType;
|
||||
Debug.Assert(owningType.IsValueType);
|
||||
|
||||
var owningTypeDefinition = (MetadataType)owningType.GetTypeDefinition();
|
||||
|
||||
// Get a reference type that has the same layout as the boxed valuetype.
|
||||
var typeKey = new BoxedValuetypeHashtableKey(owningTypeDefinition, ownerModuleOfThunk);
|
||||
BoxedValueType boxedTypeDefinition = _boxedValuetypeHashtable.GetOrCreateValue(typeKey);
|
||||
|
||||
// Get a method on the reference type with the same signature as the target method (but different
|
||||
// calling convention, since 'this' will be a reference type).
|
||||
var targetMethodDefinition = targetMethod.GetTypicalMethodDefinition();
|
||||
var methodKey = new UnboxingThunkHashtableKey(targetMethodDefinition, boxedTypeDefinition);
|
||||
UnboxingThunk thunkDefinition = _nonGenericUnboxingThunkHashtable.GetOrCreateValue(methodKey);
|
||||
|
||||
// Find the thunk on the instantiated version of the reference type.
|
||||
if (owningType != owningTypeDefinition)
|
||||
{
|
||||
InstantiatedType boxedType = boxedTypeDefinition.MakeInstantiatedType(owningType.Instantiation);
|
||||
MethodDesc thunk = GetMethodForInstantiatedType(thunkDefinition, boxedType);
|
||||
//TODO: this might be triggered by a struct that implements an interface with a generic method
|
||||
Debug.Assert(!thunk.HasInstantiation);
|
||||
return thunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: this might be triggered by a struct that implements an interface with a generic method
|
||||
Debug.Assert(!thunkDefinition.HasInstantiation);
|
||||
return thunkDefinition;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true of <paramref name="method"/> is a standin method for unboxing thunk target.
|
||||
/// </summary>
|
||||
@@ -184,7 +218,34 @@ namespace ILCompiler
|
||||
}
|
||||
}
|
||||
private UnboxingThunkHashtable _unboxingThunkHashtable = new UnboxingThunkHashtable();
|
||||
|
||||
|
||||
private class NonGenericUnboxingThunkHashtable : LockFreeReaderHashtable<UnboxingThunkHashtableKey, UnboxingThunk>
|
||||
{
|
||||
protected override int GetKeyHashCode(UnboxingThunkHashtableKey key)
|
||||
{
|
||||
return key.TargetMethod.GetHashCode();
|
||||
}
|
||||
protected override int GetValueHashCode(UnboxingThunk value)
|
||||
{
|
||||
return value.TargetMethod.GetHashCode();
|
||||
}
|
||||
protected override bool CompareKeyToValue(UnboxingThunkHashtableKey key, UnboxingThunk value)
|
||||
{
|
||||
return Object.ReferenceEquals(key.TargetMethod, value.TargetMethod) &&
|
||||
Object.ReferenceEquals(key.OwningType, value.OwningType);
|
||||
}
|
||||
protected override bool CompareValueToValue(UnboxingThunk value1, UnboxingThunk value2)
|
||||
{
|
||||
return Object.ReferenceEquals(value1.TargetMethod, value2.TargetMethod) &&
|
||||
Object.ReferenceEquals(value1.OwningType, value2.OwningType);
|
||||
}
|
||||
protected override UnboxingThunk CreateValueFromKey(UnboxingThunkHashtableKey key)
|
||||
{
|
||||
return new UnboxingThunk(key.OwningType, key.TargetMethod);
|
||||
}
|
||||
}
|
||||
|
||||
private NonGenericUnboxingThunkHashtable _nonGenericUnboxingThunkHashtable = new NonGenericUnboxingThunkHashtable();
|
||||
|
||||
/// <summary>
|
||||
/// A type with an identical layout to the layout of a boxed value type.
|
||||
@@ -210,6 +271,7 @@ namespace ILCompiler
|
||||
public override bool IsSequentialLayout => true;
|
||||
public override bool IsBeforeFieldInit => false;
|
||||
public override MetadataType MetadataBaseType => (MetadataType)Context.GetWellKnownType(WellKnownType.Object);
|
||||
public override DefType BaseType => MetadataBaseType;
|
||||
public override bool IsSealed => true;
|
||||
public override bool IsAbstract => false;
|
||||
public override DefType ContainingType => null;
|
||||
@@ -248,11 +310,6 @@ namespace ILCompiler
|
||||
return hashCodeBuilder.ToHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Boxed " + Module.ToString() + ValueTypeRepresented.ToString();
|
||||
}
|
||||
|
||||
protected override TypeFlags ComputeTypeFlags(TypeFlags mask)
|
||||
{
|
||||
TypeFlags flags = 0;
|
||||
@@ -268,6 +325,7 @@ namespace ILCompiler
|
||||
}
|
||||
|
||||
flags |= TypeFlags.HasFinalizerComputed;
|
||||
flags |= TypeFlags.IsByRefLikeComputed;
|
||||
|
||||
return flags;
|
||||
}
|
||||
@@ -414,6 +472,67 @@ namespace ILCompiler
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a thunk to call instance method on boxed valuetypes.
|
||||
/// </summary>
|
||||
private partial class UnboxingThunk : ILStubMethod
|
||||
{
|
||||
private MethodDesc _targetMethod;
|
||||
private BoxedValueType _owningType;
|
||||
|
||||
public UnboxingThunk(BoxedValueType owningType, MethodDesc targetMethod)
|
||||
{
|
||||
Debug.Assert(targetMethod.OwningType.IsValueType);
|
||||
Debug.Assert(!targetMethod.Signature.IsStatic);
|
||||
|
||||
_owningType = owningType;
|
||||
_targetMethod = targetMethod;
|
||||
}
|
||||
|
||||
public override TypeSystemContext Context => _targetMethod.Context;
|
||||
|
||||
public override TypeDesc OwningType => _owningType;
|
||||
|
||||
public override MethodSignature Signature => _targetMethod.Signature;
|
||||
|
||||
public MethodDesc TargetMethod => _targetMethod;
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _targetMethod.Name + "_Unbox";
|
||||
}
|
||||
}
|
||||
|
||||
public override MethodIL EmitIL()
|
||||
{
|
||||
// Generate the unboxing stub. This loosely corresponds to following C#:
|
||||
// return BoxedValue.InstanceMethod([rest of parameters])
|
||||
|
||||
ILEmitter emit = new ILEmitter();
|
||||
ILCodeStream codeStream = emit.NewCodeStream();
|
||||
|
||||
FieldDesc boxedValueField = _owningType.BoxedValue.InstantiateAsOpen();
|
||||
|
||||
// unbox to get a pointer to the value type
|
||||
codeStream.EmitLdArg(0);
|
||||
codeStream.Emit(ILOpcode.ldflda, emit.NewToken(boxedValueField));
|
||||
|
||||
// Load rest of the arguments
|
||||
for (int i = 0; i < _targetMethod.Signature.Length; i++)
|
||||
{
|
||||
codeStream.EmitLdArg(i + 1);
|
||||
}
|
||||
|
||||
// Call an instance method on the target valuetype
|
||||
codeStream.Emit(ILOpcode.call, emit.NewToken(_targetMethod.InstantiateAsOpen()));
|
||||
codeStream.Emit(ILOpcode.ret);
|
||||
|
||||
return emit.Link(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an instance method on a generic valuetype with an explicit instantiation parameter in the
|
||||
/// signature. This is so that we can refer to the parameter from IL. References to this method will
|
||||
|
||||
@@ -40,6 +40,17 @@ namespace ILCompiler
|
||||
}
|
||||
}
|
||||
|
||||
partial class UnboxingThunk
|
||||
{
|
||||
protected override int ClassCode => 446545583;
|
||||
|
||||
protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
|
||||
{
|
||||
var otherMethod = (UnboxingThunk)other;
|
||||
return comparer.Compare(_targetMethod, otherMethod._targetMethod);
|
||||
}
|
||||
}
|
||||
|
||||
partial class ValueTypeInstanceMethodWithHiddenParameter
|
||||
{
|
||||
protected override int ClassCode => 2131875345;
|
||||
|
||||
@@ -22,10 +22,13 @@ namespace ILCompiler
|
||||
{
|
||||
private MetadataFieldLayoutAlgorithm _metadataFieldLayoutAlgorithm = new CompilerMetadataFieldLayoutAlgorithm();
|
||||
private RuntimeDeterminedFieldLayoutAlgorithm _runtimeDeterminedFieldLayoutAlgorithm = new RuntimeDeterminedFieldLayoutAlgorithm();
|
||||
private VectorOfTFieldLayoutAlgorithm _vectorOfTFieldLayoutAlgorithm;
|
||||
private MetadataRuntimeInterfacesAlgorithm _metadataRuntimeInterfacesAlgorithm = new MetadataRuntimeInterfacesAlgorithm();
|
||||
private ArrayOfTRuntimeInterfacesAlgorithm _arrayOfTRuntimeInterfacesAlgorithm;
|
||||
private MetadataVirtualMethodAlgorithm _virtualMethodAlgorithm = new MetadataVirtualMethodAlgorithm();
|
||||
|
||||
private SimdHelper _simdHelper;
|
||||
|
||||
private TypeDesc[] _arrayOfTInterfaces;
|
||||
|
||||
private MetadataStringDecoder _metadataStringDecoder;
|
||||
@@ -59,7 +62,7 @@ namespace ILCompiler
|
||||
}
|
||||
protected override ModuleData CreateValueFromKey(EcmaModule key)
|
||||
{
|
||||
Debug.Assert(false, "CreateValueFromKey not supported");
|
||||
Debug.Fail("CreateValueFromKey not supported");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -87,7 +90,7 @@ namespace ILCompiler
|
||||
}
|
||||
protected override ModuleData CreateValueFromKey(string key)
|
||||
{
|
||||
Debug.Assert(false, "CreateValueFromKey not supported");
|
||||
Debug.Fail("CreateValueFromKey not supported");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -99,6 +102,8 @@ namespace ILCompiler
|
||||
: base(details)
|
||||
{
|
||||
_genericsMode = genericsMode;
|
||||
|
||||
_vectorOfTFieldLayoutAlgorithm = new VectorOfTFieldLayoutAlgorithm(_metadataFieldLayoutAlgorithm);
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, string> InputFilePaths
|
||||
@@ -128,7 +133,7 @@ namespace ILCompiler
|
||||
return GetModuleForSimpleName(name.Name, throwIfNotFound);
|
||||
}
|
||||
|
||||
public EcmaModule GetModuleForSimpleName(string simpleName, bool throwIfNotFound = true)
|
||||
public ModuleDesc GetModuleForSimpleName(string simpleName, bool throwIfNotFound = true)
|
||||
{
|
||||
ModuleData existing;
|
||||
if (_simpleNameHashtable.TryGetValue(simpleName, out existing))
|
||||
@@ -139,19 +144,33 @@ namespace ILCompiler
|
||||
{
|
||||
if (!ReferenceFilePaths.TryGetValue(simpleName, out filePath))
|
||||
{
|
||||
// We allow the CanonTypesModule to not be an EcmaModule.
|
||||
if (((IAssemblyDesc)CanonTypesModule).GetName().Name == simpleName)
|
||||
return CanonTypesModule;
|
||||
|
||||
// TODO: the exception is wrong for two reasons: for one, this should be assembly full name, not simple name.
|
||||
// The other reason is that on CoreCLR, the exception also captures the reason. We should be passing two
|
||||
// string IDs. This makes this rather annoying.
|
||||
if (throwIfNotFound)
|
||||
throw new TypeSystemException.FileNotFoundException(ExceptionStringID.FileLoadErrorGeneric, simpleName);
|
||||
ThrowHelper.ThrowFileNotFoundException(ExceptionStringID.FileLoadErrorGeneric, simpleName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return AddModule(filePath, simpleName);
|
||||
return AddModule(filePath, simpleName, true);
|
||||
}
|
||||
|
||||
public EcmaModule GetModuleFromPath(string filePath)
|
||||
{
|
||||
return GetOrAddModuleFromPath(filePath, true);
|
||||
}
|
||||
|
||||
public EcmaModule GetMetadataOnlyModuleFromPath(string filePath)
|
||||
{
|
||||
return GetOrAddModuleFromPath(filePath, false);
|
||||
}
|
||||
|
||||
private EcmaModule GetOrAddModuleFromPath(string filePath, bool useForBinding)
|
||||
{
|
||||
// This method is not expected to be called frequently. Linear search is acceptable.
|
||||
foreach (var entry in ModuleHashtable.Enumerator.Get(_moduleHashtable))
|
||||
@@ -160,10 +179,10 @@ namespace ILCompiler
|
||||
return entry.Module;
|
||||
}
|
||||
|
||||
return AddModule(filePath, null);
|
||||
return AddModule(filePath, null, useForBinding);
|
||||
}
|
||||
|
||||
private static unsafe PEReader OpenPEFile(string filePath, out MemoryMappedViewAccessor mappedViewAccessor)
|
||||
public static unsafe PEReader OpenPEFile(string filePath, out MemoryMappedViewAccessor mappedViewAccessor)
|
||||
{
|
||||
// System.Reflection.Metadata has heuristic that tries to save virtual address space. This heuristic does not work
|
||||
// well for us since it can make IL access very slow (call to OS for each method IL query). We will map the file
|
||||
@@ -201,7 +220,7 @@ namespace ILCompiler
|
||||
}
|
||||
}
|
||||
|
||||
private EcmaModule AddModule(string filePath, string expectedSimpleName)
|
||||
private EcmaModule AddModule(string filePath, string expectedSimpleName, bool useForBinding)
|
||||
{
|
||||
MemoryMappedViewAccessor mappedViewAccessor = null;
|
||||
PdbSymbolReader pdbReader = null;
|
||||
@@ -228,12 +247,15 @@ namespace ILCompiler
|
||||
|
||||
lock (this)
|
||||
{
|
||||
ModuleData actualModuleData = _simpleNameHashtable.AddOrGetExisting(moduleData);
|
||||
if (actualModuleData != moduleData)
|
||||
if (useForBinding)
|
||||
{
|
||||
if (actualModuleData.FilePath != filePath)
|
||||
throw new FileNotFoundException("Module with same simple name already exists " + filePath);
|
||||
return actualModuleData.Module;
|
||||
ModuleData actualModuleData = _simpleNameHashtable.AddOrGetExisting(moduleData);
|
||||
if (actualModuleData != moduleData)
|
||||
{
|
||||
if (actualModuleData.FilePath != filePath)
|
||||
throw new FileNotFoundException("Module with same simple name already exists " + filePath);
|
||||
return actualModuleData.Module;
|
||||
}
|
||||
}
|
||||
mappedViewAccessor = null; // Ownership has been transfered
|
||||
pdbReader = null; // Ownership has been transferred
|
||||
@@ -258,6 +280,8 @@ namespace ILCompiler
|
||||
return UniversalCanonLayoutAlgorithm.Instance;
|
||||
else if (type.IsRuntimeDeterminedType)
|
||||
return _runtimeDeterminedFieldLayoutAlgorithm;
|
||||
else if (_simdHelper.IsVectorOfT(type))
|
||||
return _vectorOfTFieldLayoutAlgorithm;
|
||||
else
|
||||
return _metadataFieldLayoutAlgorithm;
|
||||
}
|
||||
@@ -325,19 +349,21 @@ namespace ILCompiler
|
||||
return type.GetMethods();
|
||||
}
|
||||
|
||||
private IEnumerable<MethodDesc> GetAllMethodsForDelegate(TypeDesc type)
|
||||
protected virtual IEnumerable<MethodDesc> GetAllMethodsForDelegate(TypeDesc type)
|
||||
{
|
||||
// Inject the synthetic GetThunk virtual override
|
||||
// Inject the synthetic methods that support the implementation of the delegate.
|
||||
InstantiatedType instantiatedType = type as InstantiatedType;
|
||||
if (instantiatedType != null)
|
||||
{
|
||||
DelegateInfo info = GetDelegateInfo(type.GetTypeDefinition());
|
||||
yield return GetMethodForInstantiatedType(info.GetThunkMethod, instantiatedType);
|
||||
foreach (MethodDesc syntheticMethod in info.Methods)
|
||||
yield return GetMethodForInstantiatedType(syntheticMethod, instantiatedType);
|
||||
}
|
||||
else
|
||||
{
|
||||
DelegateInfo info = GetDelegateInfo(type);
|
||||
yield return info.GetThunkMethod;
|
||||
foreach (MethodDesc syntheticMethod in info.Methods)
|
||||
yield return syntheticMethod;
|
||||
}
|
||||
|
||||
// Append all the methods defined in metadata
|
||||
|
||||
@@ -165,6 +165,7 @@ namespace ILCompiler
|
||||
|
||||
private string EnterNameScopeSequence => _mangleForCplusPlus ? "_A_" : "<";
|
||||
private string ExitNameScopeSequence => _mangleForCplusPlus ? "_V_" : ">";
|
||||
private string DelimitNameScopeSequence => _mangleForCplusPlus? "_C_" : ",";
|
||||
|
||||
protected string NestMangledName(string name)
|
||||
{
|
||||
@@ -275,17 +276,15 @@ namespace ILCompiler
|
||||
switch (type.Category)
|
||||
{
|
||||
case TypeFlags.Array:
|
||||
mangledName = "__MDArray" +
|
||||
EnterNameScopeSequence +
|
||||
GetMangledTypeName(((ArrayType)type).ElementType) +
|
||||
DelimitNameScopeSequence +
|
||||
((ArrayType)type).Rank.ToStringInvariant() +
|
||||
ExitNameScopeSequence;
|
||||
break;
|
||||
case TypeFlags.SzArray:
|
||||
mangledName = GetMangledTypeName(((ArrayType)type).ElementType) + "__";
|
||||
|
||||
if (type.IsMdArray)
|
||||
{
|
||||
mangledName += NestMangledName("ArrayRank" + ((ArrayType)type).Rank.ToStringInvariant());
|
||||
}
|
||||
else
|
||||
{
|
||||
mangledName += NestMangledName("Array");
|
||||
}
|
||||
mangledName = "__Array" + NestMangledName(GetMangledTypeName(((ArrayType)type).ElementType));
|
||||
break;
|
||||
case TypeFlags.ByRef:
|
||||
mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + NestMangledName("ByRef");
|
||||
|
||||
30
external/corert/src/ILCompiler.Compiler/src/Compiler/DebugInformationProvider.cs
vendored
Normal file
30
external/corert/src/ILCompiler.Compiler/src/Compiler/DebugInformationProvider.cs
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// 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 Internal.IL;
|
||||
|
||||
namespace ILCompiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides debug information by delegating to the <see cref="MethodIL"/>.
|
||||
/// </summary>
|
||||
public class DebugInformationProvider
|
||||
{
|
||||
public virtual MethodDebugInformation GetDebugInfo(MethodIL methodIL)
|
||||
{
|
||||
return methodIL.GetDebugInfo();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides empty debug information.
|
||||
/// </summary>
|
||||
public sealed class NullDebugInformationProvider : DebugInformationProvider
|
||||
{
|
||||
public override MethodDebugInformation GetDebugInfo(MethodIL methodIL)
|
||||
{
|
||||
return MethodDebugInformation.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ namespace ILCompiler
|
||||
return factory.GenericLookup.MethodEntry(TargetMethod, TargetMethodIsUnboxingThunk);
|
||||
|
||||
case TargetKind.InterfaceDispatch:
|
||||
return factory.GenericLookup.VirtualMethodAddress(TargetMethod);
|
||||
return factory.GenericLookup.VirtualDispatchCell(TargetMethod);
|
||||
|
||||
case TargetKind.MethodHandle:
|
||||
return factory.GenericLookup.MethodHandle(TargetMethod);
|
||||
@@ -129,7 +129,7 @@ namespace ILCompiler
|
||||
return factory.RuntimeMethodHandle(TargetMethod);
|
||||
|
||||
case TargetKind.VTableLookup:
|
||||
Debug.Assert(false, "Need to do runtime lookup");
|
||||
Debug.Fail("Need to do runtime lookup");
|
||||
return null;
|
||||
|
||||
default:
|
||||
@@ -313,5 +313,33 @@ namespace ILCompiler
|
||||
{
|
||||
return Constructor.GetHashCode() ^ TargetMethod.GetHashCode();
|
||||
}
|
||||
|
||||
#if !SUPPORT_JIT
|
||||
internal int CompareTo(DelegateCreationInfo other, TypeSystemComparer comparer)
|
||||
{
|
||||
var compare = _targetKind - other._targetKind;
|
||||
if (compare != 0)
|
||||
return compare;
|
||||
|
||||
compare = comparer.Compare(TargetMethod, other.TargetMethod);
|
||||
if (compare != 0)
|
||||
return compare;
|
||||
|
||||
compare = comparer.Compare(Constructor.Method, other.Constructor.Method);
|
||||
if (compare != 0)
|
||||
return compare;
|
||||
|
||||
if (Thunk == other.Thunk)
|
||||
return 0;
|
||||
|
||||
if (Thunk == null)
|
||||
return -1;
|
||||
|
||||
if (other.Thunk == null)
|
||||
return 1;
|
||||
|
||||
return comparer.Compare(Thunk.Method, other.Thunk.Method);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace ILCompiler.DependencyAnalysis
|
||||
public override ObjectNodeSection Section => _externalReferences.Section;
|
||||
|
||||
public override bool StaticDependenciesAreComputed => true;
|
||||
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => !factory.MetadataManager.SupportsReflection;
|
||||
|
||||
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
|
||||
|
||||
@@ -51,7 +52,7 @@ namespace ILCompiler.DependencyAnalysis
|
||||
Section hashTableSection = writer.NewSection();
|
||||
hashTableSection.Place(typeMapHashTable);
|
||||
|
||||
foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
|
||||
foreach (var type in factory.MetadataManager.GetTypesWithConstructedEETypes())
|
||||
{
|
||||
if (!type.IsSzArray)
|
||||
continue;
|
||||
@@ -61,8 +62,8 @@ namespace ILCompiler.DependencyAnalysis
|
||||
if (!arrayType.ElementType.IsValueType)
|
||||
continue;
|
||||
|
||||
// Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
|
||||
IEETypeNode arrayTypeSymbol = factory.NecessaryTypeSymbol(arrayType);
|
||||
// Look at the constructed type symbol. If a constructed type wasn't emitted, then the array map entry isn't valid for use
|
||||
IEETypeNode arrayTypeSymbol = factory.ConstructedTypeSymbol(arrayType);
|
||||
|
||||
Vertex vertex = writer.GetUnsignedConstant(_externalReferences.GetIndex(arrayTypeSymbol));
|
||||
|
||||
@@ -76,5 +77,8 @@ namespace ILCompiler.DependencyAnalysis
|
||||
|
||||
return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol });
|
||||
}
|
||||
|
||||
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
|
||||
protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayMapNode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,30 +11,28 @@ using Internal.TypeSystem;
|
||||
|
||||
namespace ILCompiler.DependencyAnalysis
|
||||
{
|
||||
public interface IHasStartSymbol
|
||||
{
|
||||
ObjectAndOffsetSymbolNode StartSymbol { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an array of <typeparamref name="TEmbedded"/> nodes. The contents of this node will be emitted
|
||||
/// by placing a starting symbol, followed by contents of <typeparamref name="TEmbedded"/> nodes (optionally
|
||||
/// sorted using provided comparer), followed by ending symbol.
|
||||
/// </summary>
|
||||
public class ArrayOfEmbeddedDataNode<TEmbedded> : ObjectNode
|
||||
public class ArrayOfEmbeddedDataNode<TEmbedded> : EmbeddedDataContainerNode, IHasStartSymbol
|
||||
where TEmbedded : EmbeddedObjectNode
|
||||
{
|
||||
private HashSet<TEmbedded> _nestedNodes = new HashSet<TEmbedded>();
|
||||
private List<TEmbedded> _nestedNodesList = new List<TEmbedded>();
|
||||
private ObjectAndOffsetSymbolNode _startSymbol;
|
||||
private ObjectAndOffsetSymbolNode _endSymbol;
|
||||
private IComparer<TEmbedded> _sorter;
|
||||
|
||||
public ArrayOfEmbeddedDataNode(string startSymbolMangledName, string endSymbolMangledName, IComparer<TEmbedded> nodeSorter)
|
||||
public ArrayOfEmbeddedDataNode(string startSymbolMangledName, string endSymbolMangledName, IComparer<TEmbedded> nodeSorter) : base(startSymbolMangledName, endSymbolMangledName)
|
||||
{
|
||||
_startSymbol = new ObjectAndOffsetSymbolNode(this, 0, startSymbolMangledName, true);
|
||||
_endSymbol = new ObjectAndOffsetSymbolNode(this, 0, endSymbolMangledName, true);
|
||||
_sorter = nodeSorter;
|
||||
}
|
||||
|
||||
public ObjectAndOffsetSymbolNode StartSymbol => _startSymbol;
|
||||
public ObjectAndOffsetSymbolNode EndSymbol => _endSymbol;
|
||||
|
||||
|
||||
public void AddEmbeddedObject(TEmbedded symbol)
|
||||
{
|
||||
lock (_nestedNodes)
|
||||
@@ -43,16 +41,11 @@ namespace ILCompiler.DependencyAnalysis
|
||||
{
|
||||
_nestedNodesList.Add(symbol);
|
||||
}
|
||||
symbol.ContainingNode = this;
|
||||
}
|
||||
}
|
||||
|
||||
public int IndexOfEmbeddedObject(TEmbedded symbol)
|
||||
{
|
||||
Debug.Assert(_sorter == null);
|
||||
return _nestedNodesList.IndexOf(symbol);
|
||||
}
|
||||
|
||||
protected override string GetName(NodeFactory factory) => $"Region {_startSymbol.GetMangledName(factory.NameMangler)}";
|
||||
protected override string GetName(NodeFactory factory) => $"Region {StartSymbol.GetMangledName(factory.NameMangler)}";
|
||||
|
||||
public override ObjectNodeSection Section => ObjectNodeSection.DataSection;
|
||||
public override bool IsShareable => false;
|
||||
@@ -63,10 +56,14 @@ namespace ILCompiler.DependencyAnalysis
|
||||
|
||||
protected virtual void GetElementDataForNodes(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (TEmbedded node in NodesList)
|
||||
{
|
||||
if (!relocsOnly)
|
||||
{
|
||||
node.InitializeOffsetFromBeginningOfArray(builder.CountBytes);
|
||||
node.InitializeIndexFromBeginningOfArray(index++);
|
||||
}
|
||||
|
||||
node.EncodeData(ref builder, factory, relocsOnly);
|
||||
if (node is ISymbolDefinitionNode)
|
||||
@@ -84,12 +81,12 @@ namespace ILCompiler.DependencyAnalysis
|
||||
if (_sorter != null)
|
||||
_nestedNodesList.Sort(_sorter);
|
||||
|
||||
builder.AddSymbol(_startSymbol);
|
||||
builder.AddSymbol(StartSymbol);
|
||||
|
||||
GetElementDataForNodes(ref builder, factory, relocsOnly);
|
||||
|
||||
_endSymbol.SetSymbolOffset(builder.CountBytes);
|
||||
builder.AddSymbol(_endSymbol);
|
||||
EndSymbol.SetSymbolOffset(builder.CountBytes);
|
||||
builder.AddSymbol(EndSymbol);
|
||||
|
||||
ObjectData objData = builder.ToObjectData();
|
||||
return objData;
|
||||
@@ -108,15 +105,9 @@ namespace ILCompiler.DependencyAnalysis
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: delete this once we review each use of this and put it on the generic plan with the
|
||||
// right element type
|
||||
public class ArrayOfEmbeddedDataNode : ArrayOfEmbeddedDataNode<EmbeddedObjectNode>
|
||||
{
|
||||
public ArrayOfEmbeddedDataNode(string startSymbolMangledName, string endSymbolMangledName, IComparer<EmbeddedObjectNode> nodeSorter)
|
||||
: base(startSymbolMangledName, endSymbolMangledName, nodeSorter)
|
||||
{
|
||||
}
|
||||
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
|
||||
|
||||
protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedDataNode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace ILCompiler.DependencyAnalysis
|
||||
/// of node each pointer within the vector points to.
|
||||
/// </summary>
|
||||
public sealed class ArrayOfEmbeddedPointersNode<TTarget> : ArrayOfEmbeddedDataNode<EmbeddedPointerIndirectionNode<TTarget>>
|
||||
where TTarget : ISymbolNode
|
||||
where TTarget : ISortableSymbolNode
|
||||
{
|
||||
private int _nextId;
|
||||
private string _startSymbolMangledName;
|
||||
@@ -44,16 +44,15 @@ namespace ILCompiler.DependencyAnalysis
|
||||
return new EmbeddedPointerIndirectionWithSymbolNode(this, target, GetNextId());
|
||||
}
|
||||
|
||||
public EmbeddedObjectNode NewNodeWithSymbol(TTarget target, OnMarkedDelegate callback)
|
||||
{
|
||||
return new EmbeddedPointerIndirectionWithSymbolAndOnMarkedCallbackNode(this, target, GetNextId(), callback);
|
||||
}
|
||||
|
||||
int GetNextId()
|
||||
{
|
||||
return System.Threading.Interlocked.Increment(ref _nextId);
|
||||
}
|
||||
|
||||
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
|
||||
|
||||
protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedPointersNode;
|
||||
|
||||
private class PointerIndirectionNodeComparer : IComparer<EmbeddedPointerIndirectionNode<TTarget>>
|
||||
{
|
||||
private IComparer<TTarget> _innerComparer;
|
||||
@@ -96,6 +95,8 @@ namespace ILCompiler.DependencyAnalysis
|
||||
new DependencyListEntry(_parentNode, "Pointer region")
|
||||
};
|
||||
}
|
||||
|
||||
protected internal override int ClassCode => -66002498;
|
||||
}
|
||||
|
||||
private class EmbeddedPointerIndirectionWithSymbolNode : SimpleEmbeddedPointerIndirectionNode, ISymbolDefinitionNode
|
||||
@@ -113,27 +114,10 @@ namespace ILCompiler.DependencyAnalysis
|
||||
|
||||
int ISymbolDefinitionNode.Offset => OffsetFromBeginningOfArray;
|
||||
|
||||
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
|
||||
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
|
||||
{
|
||||
sb.Append(nameMangler.CompilationUnitPrefix).Append(_parentNode._startSymbolMangledName).Append("_").Append(_id.ToStringInvariant());
|
||||
}
|
||||
}
|
||||
|
||||
private class EmbeddedPointerIndirectionWithSymbolAndOnMarkedCallbackNode : EmbeddedPointerIndirectionWithSymbolNode
|
||||
{
|
||||
private OnMarkedDelegate _onMarkedCallback;
|
||||
|
||||
public EmbeddedPointerIndirectionWithSymbolAndOnMarkedCallbackNode(ArrayOfEmbeddedPointersNode<TTarget> futureParent, TTarget target, int id, OnMarkedDelegate onMarkedCallback)
|
||||
: base(futureParent, target, id)
|
||||
{
|
||||
_onMarkedCallback = onMarkedCallback;
|
||||
}
|
||||
|
||||
protected override void OnMarked(NodeFactory factory)
|
||||
{
|
||||
base.OnMarked(factory);
|
||||
_onMarkedCallback(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user