diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs b/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs
index 316a31de731..4c8101df202 100644
--- a/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs
@@ -100,5 +100,21 @@ public abstract class CompilationModuleGroup
/// The called method to be inlined into the caller
///
public virtual bool CanInline(MethodDesc callerMethod, MethodDesc calleeMethod) => true;
+
+ ///
+ /// Returns true when a given type belongs to the same version bubble as the compilation module group.
+ /// By default return the same outcome as ContainsType.
+ ///
+ /// Type to check
+ /// True if the given type versions with the current compilation module group
+ public virtual bool VersionsWithType(TypeDesc typeDesc) => ContainsType(typeDesc);
+
+ ///
+ /// Returns true when a given method belongs to the same version bubble as the compilation module group.
+ /// By default return the same outcome as ContainsMethodBody.
+ ///
+ /// Method to check
+ /// True if the given method versions with the current compilation module group
+ public virtual bool VersionsWithMethodBody(MethodDesc methodDesc) => ContainsMethodBody(methodDesc, unboxingStub: false);
}
}
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs
index fd9b06650c6..efbad225087 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs
@@ -38,21 +38,24 @@ public DelegateCtorSignature(
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
+ ReadyToRunCodegenNodeFactory r2rFactory = (ReadyToRunCodegenNodeFactory)factory;
ObjectDataSignatureBuilder builder = new ObjectDataSignatureBuilder();
builder.AddSymbol(this);
if (!relocsOnly)
{
- builder.EmitByte((byte)ReadyToRunFixupKind.READYTORUN_FIXUP_DelegateCtor);
+ SignatureContext innerContext = builder.EmitFixup(r2rFactory, ReadyToRunFixupKind.READYTORUN_FIXUP_DelegateCtor, _methodToken.Module, _signatureContext);
+
builder.EmitMethodSignature(
_targetMethod.Method,
constrainedType: null,
methodToken: _methodToken,
enforceDefEncoding: false,
- _signatureContext,
+ innerContext,
isUnboxingStub: false,
isInstantiatingStub: false);
- builder.EmitTypeSignature(_delegateType, _signatureContext);
+
+ builder.EmitTypeSignature(_delegateType, innerContext);
}
return builder.ToObjectData();
@@ -71,7 +74,13 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix);
- sb.Append($@"DelegateCtor({_delegateType} -> {_targetMethod.Method})");
+ sb.Append($@"DelegateCtor(");
+ sb.Append(nameMangler.GetMangledTypeName(_delegateType));
+ sb.Append(" -> ");
+ sb.Append(nameMangler.GetMangledMethodName(_targetMethod.Method));
+ sb.Append("; ");
+ sb.Append(_methodToken.ToString());
+ sb.Append(")");
}
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/FieldFixupSignature.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/FieldFixupSignature.cs
index 21ad6039d44..ba0dda78b9f 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/FieldFixupSignature.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/FieldFixupSignature.cs
@@ -7,6 +7,7 @@
using Internal.JitInterface;
using Internal.Text;
using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
@@ -36,8 +37,10 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
dataBuilder.AddSymbol(this);
- dataBuilder.EmitByte((byte)_fixupKind);
- dataBuilder.EmitFieldSignature(_fieldDesc, _signatureContext);
+ EcmaModule targetModule = _signatureContext.GetTargetModule(_fieldDesc);
+ SignatureContext innerContext = dataBuilder.EmitFixup(r2rFactory, _fixupKind, targetModule, _signatureContext);
+
+ dataBuilder.EmitFieldSignature(_fieldDesc, innerContext);
}
return dataBuilder.ToObjectData();
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/FixupConstants.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/FixupConstants.cs
index 8f9c2f94b78..8116e1ac195 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/FixupConstants.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/FixupConstants.cs
@@ -71,6 +71,7 @@ public enum DictionaryEntryKind
DeclaringTypeHandleSlot = 7,
}
+ [Flags]
public enum ReadyToRunFixupKind
{
READYTORUN_FIXUP_Invalid = 0x00,
@@ -120,6 +121,12 @@ public enum ReadyToRunFixupKind
READYTORUN_FIXUP_DelegateCtor = 0x2C, /* optimized delegate ctor */
READYTORUN_FIXUP_DeclaringTypeHandle = 0x2D,
+
+ READYTORUN_FIXUP_ModuleOverride = 0x80,
+ // followed by sig-encoded UInt with assemblyref index into either the assemblyref
+ // table of the MSIL metadata of the master context module for the signature or
+ // into the extra assemblyref table in the manifest metadata R2R header table
+ // (used in cases inlining brings in references to assemblies not seen in the MSIL).
}
//
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs
index 4f31ff29664..38882695480 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs
@@ -8,12 +8,13 @@
using Internal.JitInterface;
using Internal.Text;
using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
public class GenericLookupSignature : Signature
{
- private CORINFO_RUNTIME_LOOKUP_KIND _runtimeLookupKind;
+ private readonly CORINFO_RUNTIME_LOOKUP_KIND _runtimeLookupKind;
private readonly ReadyToRunFixupKind _fixupKind;
@@ -28,9 +29,9 @@ public class GenericLookupSignature : Signature
private readonly SignatureContext _signatureContext;
public GenericLookupSignature(
- CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind,
- ReadyToRunFixupKind fixupKind,
- TypeDesc typeArgument,
+ CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind,
+ ReadyToRunFixupKind fixupKind,
+ TypeDesc typeArgument,
MethodWithToken methodArgument,
FieldDesc fieldArgument,
GenericContext methodContext,
@@ -50,56 +51,86 @@ public GenericLookupSignature(
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
+ if (relocsOnly)
+ {
+ return new ObjectData(Array.Empty(), null, 1, null);
+ }
+
ReadyToRunCodegenNodeFactory r2rFactory = (ReadyToRunCodegenNodeFactory)factory;
- ObjectDataSignatureBuilder dataBuilder = new ObjectDataSignatureBuilder();
- if (!relocsOnly)
+ // Determine the need for module override
+ EcmaModule targetModule;
+ if (_methodArgument != null)
{
- dataBuilder.AddSymbol(this);
+ targetModule = _methodArgument.Token.Module;
+ }
+ else if (_typeArgument != null)
+ {
+ targetModule = _signatureContext.GetTargetModule(_typeArgument);
+ }
+ else if (_fieldArgument != null)
+ {
+ targetModule = _signatureContext.GetTargetModule(_fieldArgument);
+ }
+ else
+ {
+ throw new NotImplementedException();
+ }
- switch (_runtimeLookupKind)
- {
- case CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_CLASSPARAM:
- dataBuilder.EmitByte((byte)ReadyToRunFixupKind.READYTORUN_FIXUP_TypeDictionaryLookup);
- break;
+ ReadyToRunFixupKind fixupToEmit;
+ TypeDesc contextTypeToEmit = null;
- case CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_METHODPARAM:
- dataBuilder.EmitByte((byte)ReadyToRunFixupKind.READYTORUN_FIXUP_MethodDictionaryLookup);
- break;
+ switch (_runtimeLookupKind)
+ {
+ case CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_CLASSPARAM:
+ fixupToEmit = ReadyToRunFixupKind.READYTORUN_FIXUP_TypeDictionaryLookup;
+ break;
- case CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ:
- dataBuilder.EmitByte((byte)ReadyToRunFixupKind.READYTORUN_FIXUP_ThisObjDictionaryLookup);
- dataBuilder.EmitTypeSignature(_methodContext.ContextType, _signatureContext);
- break;
+ case CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_METHODPARAM:
+ fixupToEmit = ReadyToRunFixupKind.READYTORUN_FIXUP_MethodDictionaryLookup;
+ break;
- default:
- throw new NotImplementedException();
- }
+ case CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ:
+ fixupToEmit = ReadyToRunFixupKind.READYTORUN_FIXUP_ThisObjDictionaryLookup;
+ contextTypeToEmit = _methodContext.ContextType;
+ break;
- dataBuilder.EmitByte((byte)_fixupKind);
- if (_methodArgument != null)
- {
- dataBuilder.EmitMethodSignature(
- method: _methodArgument.Method,
- constrainedType: _typeArgument,
- methodToken: _methodArgument.Token,
- enforceDefEncoding: false,
- context: _signatureContext,
- isUnboxingStub: false,
- isInstantiatingStub: true);
- }
- else if (_typeArgument != null)
- {
- dataBuilder.EmitTypeSignature(_typeArgument, _signatureContext);
- }
- else if (_fieldArgument != null)
- {
- dataBuilder.EmitFieldSignature(_fieldArgument, _signatureContext);
- }
- else
- {
+ default:
throw new NotImplementedException();
- }
+ }
+
+ ObjectDataSignatureBuilder dataBuilder = new ObjectDataSignatureBuilder();
+ dataBuilder.AddSymbol(this);
+
+ SignatureContext innerContext = dataBuilder.EmitFixup(r2rFactory, fixupToEmit, targetModule, _signatureContext);
+ if (contextTypeToEmit != null)
+ {
+ dataBuilder.EmitTypeSignature(contextTypeToEmit, innerContext);
+ }
+
+ dataBuilder.EmitByte((byte)_fixupKind);
+ if (_methodArgument != null)
+ {
+ dataBuilder.EmitMethodSignature(
+ method: _methodArgument.Method,
+ constrainedType: _typeArgument,
+ methodToken: _methodArgument.Token,
+ enforceDefEncoding: false,
+ context: innerContext,
+ isUnboxingStub: false,
+ isInstantiatingStub: true);
+ }
+ else if (_typeArgument != null)
+ {
+ dataBuilder.EmitTypeSignature(_typeArgument, innerContext);
+ }
+ else if (_fieldArgument != null)
+ {
+ dataBuilder.EmitFieldSignature(_fieldArgument, innerContext);
+ }
+ else
+ {
+ throw new NotImplementedException();
}
return dataBuilder.ToObjectData();
@@ -115,7 +146,7 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde
sb.Append(": ");
if (_methodArgument != null)
{
- RuntimeDeterminedTypeHelper.WriteTo(_methodArgument.Method, sb);
+ sb.Append(nameMangler.GetMangledMethodName(_methodArgument.Method));
if (!_methodArgument.Token.IsNull)
{
sb.Append(" [");
@@ -127,11 +158,11 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde
}
if (_typeArgument != null)
{
- RuntimeDeterminedTypeHelper.WriteTo(_typeArgument, sb);
+ sb.Append(nameMangler.GetMangledTypeName(_typeArgument));
}
if (_fieldArgument != null)
{
- RuntimeDeterminedTypeHelper.WriteTo(_fieldArgument, sb);
+ sb.Append(nameMangler.GetMangledFieldName(_fieldArgument));
}
sb.Append(" (");
_methodContext.AppendMangledName(nameMangler, sb);
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs
index 6143c35d422..eeed8216518 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs
@@ -2,6 +2,7 @@
// 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;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
@@ -11,6 +12,8 @@ public class ImportSectionNode : EmbeddedObjectNode
private readonly ArrayOfEmbeddedDataNode _imports;
// TODO: annoying - today there's no way to put signature RVA's into R/O data section
private readonly ArrayOfEmbeddedPointersNode _signatures;
+ // TODO: annoying - cannot enumerate the ArrayOfEmbeddedPointersNode so we must keep a copy.
+ private readonly List _signatureList;
private readonly GCRefMapNode _gcRefMap;
private readonly CorCompileImportType _type;
@@ -20,6 +23,8 @@ public class ImportSectionNode : EmbeddedObjectNode
private readonly bool _emitPrecode;
private readonly bool _emitGCRefMap;
+ private bool _materializedSignature;
+
public ImportSectionNode(string name, CorCompileImportType importType, CorCompileImportFlags flags, byte entrySize, bool emitPrecode, bool emitGCRefMap)
{
_name = name;
@@ -31,13 +36,32 @@ public ImportSectionNode(string name, CorCompileImportType importType, CorCompil
_imports = new ArrayOfEmbeddedDataNode(_name + "_ImportBegin", _name + "_ImportEnd", null);
_signatures = new ArrayOfEmbeddedPointersNode(_name + "_SigBegin", _name + "_SigEnd", null);
+ _signatureList = new List();
_gcRefMap = (_emitGCRefMap ? new GCRefMapNode(this) : null);
}
+ public void MaterializeSignature(ReadyToRunCodegenNodeFactory r2rFactory)
+ {
+ if (!_materializedSignature)
+ {
+ foreach (Signature signature in _signatureList)
+ {
+ signature.GetData(r2rFactory, relocsOnly: false);
+ }
+ _materializedSignature = true;
+ }
+ }
+
public void AddImport(NodeFactory factory, Import import)
{
+ if (_materializedSignature)
+ {
+ throw new Exception("Cannot call AddImport after MaterializeSignature");
+ }
+
_imports.AddEmbeddedObject(import);
_signatures.AddEmbeddedObject(import.ImportSignature);
+ _signatureList.Add(import.ImportSignature.Target);
if (_emitGCRefMap)
{
_gcRefMap.AddImport(import);
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionsTableNode.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionsTableNode.cs
index fbd5d42e2b4..98a37ca62e1 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionsTableNode.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionsTableNode.cs
@@ -6,13 +6,31 @@
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
- public class ImportSectionsTableNode : ArrayOfEmbeddedDataNode
- {
- public ImportSectionsTableNode(TargetDetails target)
+ public class ImportSectionsTableNode : ArrayOfEmbeddedDataNode, ISignatureEmitter
+ {
+ private readonly ReadyToRunCodegenNodeFactory _r2rFactory;
+
+ private bool _materializedSignature;
+
+ public ImportSectionsTableNode(ReadyToRunCodegenNodeFactory r2rFactory)
: base("ImportSectionsTableStart", "ImportSectionsTableEnd", null)
{
+ _r2rFactory = r2rFactory;
+ _r2rFactory.ManifestMetadataTable.RegisterEmitter(this);
+ }
+
+ public void MaterializeSignature()
+ {
+ if (!_materializedSignature)
+ {
+ foreach (ImportSectionNode importSection in NodesList)
+ {
+ importSection.MaterializeSignature(_r2rFactory);
+ }
+ _materializedSignature = true;
+ }
}
-
+
protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly)
{
builder.RequireInitialPointerAlignment();
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs
index af0eebdced9..b879a996f1f 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs
@@ -52,11 +52,18 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
int methodIndex = r2rFactory.RuntimeFunctionsTable.GetIndex(method);
+ ModuleToken moduleToken = method.SignatureContext.GetModuleTokenForMethod(method.Method.GetTypicalMethodDefinition());
+ if (moduleToken.Module != r2rFactory.InputModuleContext.GlobalContext)
+ {
+ // TODO: encoding of instance methods relative to other modules within the version bubble
+ continue;
+ }
+
ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder();
signatureBuilder.EmitMethodSignature(
method.Method,
constrainedType: null,
- default(ModuleToken),
+ moduleToken,
enforceDefEncoding: true,
method.SignatureContext,
isUnboxingStub: false,
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs
new file mode 100644
index 00000000000..c4c8c8d078a
--- /dev/null
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs
@@ -0,0 +1,188 @@
+// 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 System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+
+using Internal.Text;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+using Debug = System.Diagnostics.Debug;
+
+namespace ILCompiler.DependencyAnalysis.ReadyToRun
+{
+ ///
+ /// Signature emitters need to register themselves with the manifest metadata table;
+ /// this is needed so that the manifest metadata can force all signatures to materialize,
+ /// and, in doing so, all extra reference modules to be emitted to the manifest metadata.
+ ///
+ public interface ISignatureEmitter
+ {
+ void MaterializeSignature();
+ }
+
+ public class ManifestMetadataTableNode : HeaderTableNode
+ {
+ ///
+ /// Map from simple assembly names to their module indices. The map gets prepopulated
+ /// with AssemblyRef's from the input module and subsequently expanded by adding entries
+ /// recorded in the manifest metadata.
+ ///
+ private readonly Dictionary _assemblyRefToModuleIdMap;
+
+ ///
+ /// Assembly references to store in the manifest metadata.
+ ///
+ private readonly List _manifestAssemblies;
+
+ ///
+ /// Registered signature emitters.
+ ///
+ private readonly List _signatureEmitters;
+
+ ///
+ /// ID corresponding to the next manifest metadata assemblyref entry.
+ ///
+ private int _nextModuleId;
+
+ ///
+ /// Set to true after GetData has been called. After that, ModuleToIndex may be called no more.
+ ///
+ private bool _emissionCompleted;
+
+ ///
+ /// Name of the input assembly.
+ ///
+ private string _inputModuleName;
+
+ public ManifestMetadataTableNode(EcmaModule inputModule)
+ : base(inputModule.Context.Target)
+ {
+ _assemblyRefToModuleIdMap = new Dictionary();
+ _manifestAssemblies = new List();
+ _signatureEmitters = new List();
+
+ _inputModuleName = inputModule.Assembly.GetName().Name;
+
+ int assemblyRefCount = inputModule.MetadataReader.GetTableRowCount(TableIndex.AssemblyRef);
+ for (int assemblyRefIndex = 1; assemblyRefIndex <= assemblyRefCount; assemblyRefIndex++)
+ {
+ AssemblyReferenceHandle assemblyRefHandle = MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex);
+ AssemblyReference assemblyRef = inputModule.MetadataReader.GetAssemblyReference(assemblyRefHandle);
+ string assemblyName = inputModule.MetadataReader.GetString(assemblyRef.Name);
+ _assemblyRefToModuleIdMap[assemblyName] = assemblyRefIndex;
+ }
+
+ // AssemblyRefCount + 1 corresponds to ROWID 0 in the manifest metadata
+ _nextModuleId = assemblyRefCount + 2;
+ }
+
+ public void RegisterEmitter(ISignatureEmitter emitter)
+ {
+ _signatureEmitters.Add(emitter);
+ }
+
+ public int ModuleToIndex(EcmaModule module)
+ {
+ AssemblyName assemblyName = module.Assembly.GetName();
+ int assemblyRefIndex;
+ if (!_assemblyRefToModuleIdMap.TryGetValue(assemblyName.Name, out assemblyRefIndex))
+ {
+ if (_emissionCompleted)
+ {
+ throw new Exception("mustn't add new assemblies after signatures have been materialized");
+ }
+
+ assemblyRefIndex = _nextModuleId++;
+ _manifestAssemblies.Add(assemblyName);
+ _assemblyRefToModuleIdMap.Add(assemblyName.Name, assemblyRefIndex);
+ }
+ return assemblyRefIndex;
+ }
+
+ public override int ClassCode => 791828335;
+
+ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
+ {
+ sb.Append("ManifestMetadataTableNode");
+ }
+
+ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
+ {
+ if (relocsOnly)
+ {
+ return new ObjectData(Array.Empty(), null, 1, null);
+ }
+
+ if (!_emissionCompleted)
+ {
+ foreach (ISignatureEmitter emitter in _signatureEmitters)
+ {
+ emitter.MaterializeSignature();
+ }
+
+ _emissionCompleted = true;
+ }
+
+ MetadataBuilder metadataBuilder = new MetadataBuilder();
+
+ metadataBuilder.AddAssembly(
+ metadataBuilder.GetOrAddString(_inputModuleName),
+ new Version(0, 0, 0, 0),
+ culture: default(StringHandle),
+ publicKey: default(BlobHandle),
+ flags: default(AssemblyFlags),
+ hashAlgorithm: AssemblyHashAlgorithm.None);
+
+ metadataBuilder.AddModule(
+ 0,
+ metadataBuilder.GetOrAddString(_inputModuleName),
+ default(GuidHandle), default(GuidHandle), default(GuidHandle));
+
+ // Module type
+ metadataBuilder.AddTypeDefinition(
+ default(TypeAttributes),
+ default(StringHandle),
+ metadataBuilder.GetOrAddString(""),
+ baseType: default(EntityHandle),
+ fieldList: MetadataTokens.FieldDefinitionHandle(1),
+ methodList: MetadataTokens.MethodDefinitionHandle(1));
+
+ foreach (AssemblyName assemblyName in _manifestAssemblies)
+ {
+ AssemblyFlags assemblyFlags = 0;
+ if ((assemblyName.Flags & AssemblyNameFlags.PublicKey) != 0)
+ {
+ assemblyFlags |= AssemblyFlags.PublicKey;
+ }
+ if ((assemblyName.Flags & AssemblyNameFlags.Retargetable) != 0)
+ {
+ assemblyFlags |= AssemblyFlags.Retargetable;
+ }
+
+ AssemblyReferenceHandle newHandle = metadataBuilder.AddAssemblyReference(
+ name: metadataBuilder.GetOrAddString(assemblyName.Name),
+ version: assemblyName.Version,
+ culture: metadataBuilder.GetOrAddString(assemblyName.CultureName),
+ publicKeyOrToken: metadataBuilder.GetOrAddBlob(assemblyName.GetPublicKeyToken()),
+ flags: assemblyFlags,
+ hashValue: default(BlobHandle) /* TODO */);
+ }
+
+ MetadataRootBuilder metadataRootBuilder = new MetadataRootBuilder(metadataBuilder);
+ BlobBuilder metadataBlobBuilder = new BlobBuilder();
+ metadataRootBuilder.Serialize(metadataBlobBuilder, methodBodyStreamRva: 0, mappedFieldDataStreamRva: 0);
+
+ return new ObjectData(
+ data: metadataBlobBuilder.ToArray(),
+ relocs: Array.Empty(),
+ alignment: 1,
+ definedSymbols: new ISymbolDefinitionNode[] { this });
+ }
+ }
+}
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs
index 71d7268e8fa..9310f3338c0 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs
@@ -58,10 +58,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
ReadyToRunCodegenNodeFactory r2rFactory = (ReadyToRunCodegenNodeFactory)factory;
ObjectDataSignatureBuilder dataBuilder = new ObjectDataSignatureBuilder();
dataBuilder.AddSymbol(this);
-
- dataBuilder.EmitByte((byte)_fixupKind);
+ SignatureContext innerContext = dataBuilder.EmitFixup(r2rFactory, _fixupKind, _methodToken.Module, _signatureContext);
dataBuilder.EmitMethodSignature(_methodDesc, _constrainedType, _methodToken, enforceDefEncoding: false,
- _signatureContext, _isUnboxingStub, _isInstantiatingStub);
+ innerContext, _isUnboxingStub, _isInstantiatingStub);
return dataBuilder.ToObjectData();
}
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ModuleToken.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ModuleToken.cs
index c7d751dea33..f30a063a67e 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ModuleToken.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ModuleToken.cs
@@ -78,7 +78,7 @@ public int CompareTo(ModuleToken other)
public SignatureContext SignatureContext(ModuleTokenResolver resolver)
{
- return new SignatureContext(resolver);
+ return new SignatureContext(Module, resolver);
}
public MetadataReader MetadataReader => Module.PEReader.GetMetadataReader();
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ModuleTokenResolver.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ModuleTokenResolver.cs
index a482816fc4a..22e040ff1dc 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ModuleTokenResolver.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/ModuleTokenResolver.cs
@@ -33,15 +33,22 @@ public class ModuleTokenResolver
private readonly CompilerTypeSystemContext _typeSystemContext;
+ private Func _moduleIndexLookup;
+
public ModuleTokenResolver(CompilationModuleGroup compilationModuleGroup, CompilerTypeSystemContext typeSystemContext)
{
_compilationModuleGroup = compilationModuleGroup;
_typeSystemContext = typeSystemContext;
}
+ public void SetModuleIndexLookup(Func moduleIndexLookup)
+ {
+ _moduleIndexLookup = moduleIndexLookup;
+ }
+
public ModuleToken GetModuleTokenForType(EcmaType type, bool throwIfNotFound = true)
{
- if (_compilationModuleGroup.ContainsType(type))
+ if (_compilationModuleGroup.VersionsWithType(type))
{
return new ModuleToken(type.EcmaModule, (mdToken)MetadataTokens.GetToken(type.Handle));
}
@@ -65,7 +72,9 @@ public ModuleToken GetModuleTokenForType(EcmaType type, bool throwIfNotFound = t
public ModuleToken GetModuleTokenForMethod(MethodDesc method, bool throwIfNotFound = true)
{
- if (_compilationModuleGroup.ContainsMethodBody(method, unboxingStub: false) &&
+ method = method.GetCanonMethodTarget(CanonicalFormKind.Specific);
+
+ if (_compilationModuleGroup.VersionsWithMethodBody(method) &&
method is EcmaMethod ecmaMethod)
{
return new ModuleToken(ecmaMethod.Module, ecmaMethod.Handle);
@@ -84,13 +93,20 @@ public ModuleToken GetModuleTokenForMethod(MethodDesc method, bool throwIfNotFou
public ModuleToken GetModuleTokenForField(FieldDesc field, bool throwIfNotFound = true)
{
- if (_compilationModuleGroup.ContainsType(field.OwningType) && field is EcmaField ecmaField)
+ if (_compilationModuleGroup.VersionsWithType(field.OwningType) && field is EcmaField ecmaField)
{
return new ModuleToken(ecmaField.Module, ecmaField.Handle);
}
+ TypeDesc owningCanonType = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific);
+ FieldDesc canonField = field;
+ if (owningCanonType != field.OwningType)
+ {
+ canonField = _typeSystemContext.GetFieldForInstantiatedType(field.GetTypicalFieldDefinition(), (InstantiatedType)owningCanonType);
+ }
+
ModuleToken token;
- if (_fieldToRefTokens.TryGetValue(field, out token))
+ if (_fieldToRefTokens.TryGetValue(canonField, out token))
{
return token;
}
@@ -132,7 +148,7 @@ private void AddModuleTokenForFieldReference(TypeDesc owningType, ModuleToken to
public void AddModuleTokenForField(FieldDesc field, ModuleToken token)
{
- if (_compilationModuleGroup.ContainsType(field.OwningType) && field.OwningType is EcmaType)
+ if (_compilationModuleGroup.VersionsWithType(field.OwningType) && field.OwningType is EcmaType)
{
// We don't need to store handles within the current compilation group
// as we can read them directly from the ECMA objects.
@@ -169,7 +185,7 @@ public void AddModuleTokenForType(TypeDesc type, ModuleToken token)
specialTypeFound = true;
}
- if (_compilationModuleGroup.ContainsType(type))
+ if (_compilationModuleGroup.VersionsWithType(type))
{
// We don't need to store handles within the current compilation group
// as we can read them directly from the ECMA objects.
@@ -190,6 +206,11 @@ public void AddModuleTokenForType(TypeDesc type, ModuleToken token)
}
}
+ public int GetModuleIndex(EcmaModule module)
+ {
+ return _moduleIndexLookup(module);
+ }
+
///
/// As of 8/20/2018, recursive propagation of type information through
/// the composite signature tree is not needed for anything. We're adding
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs
index e38b63a9a86..4345ad15b90 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs
@@ -37,7 +37,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix);
- sb.Append($@"NewArraySignature: {_arrayType.ToString()}");
+ sb.Append($@"NewArraySignature: ");
+ sb.Append(nameMangler.GetMangledTypeName(_arrayType));
}
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/NewObjectFixupSignature.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/NewObjectFixupSignature.cs
index 6de578ee80e..d4a9d15d6b3 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/NewObjectFixupSignature.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/NewObjectFixupSignature.cs
@@ -33,8 +33,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
dataBuilder.AddSymbol(this);
- dataBuilder.EmitByte((byte)ReadyToRunFixupKind.READYTORUN_FIXUP_NewObject);
- dataBuilder.EmitTypeSignature(_typeDesc, _signatureContext);
+ EcmaModule targetModule = _signatureContext.GetTargetModule(_typeDesc);
+ SignatureContext innerContext = dataBuilder.EmitFixup(r2rFactory, ReadyToRunFixupKind.READYTORUN_FIXUP_NewObject, targetModule, _signatureContext);
+ dataBuilder.EmitTypeSignature(_typeDesc, innerContext);
}
return dataBuilder.ToObjectData();
@@ -43,7 +44,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix);
- sb.Append($@"NewObjectSignature: {_typeDesc.ToString()}");
+ sb.Append($@"NewObjectSignature: ");
+ sb.Append(nameMangler.GetMangledTypeName(_typeDesc));
}
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/SignatureBuilder.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/SignatureBuilder.cs
index 919089c56aa..52ec980b73a 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/SignatureBuilder.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/SignatureBuilder.cs
@@ -298,23 +298,39 @@ public void EmitTypeSignature(TypeDesc typeDesc, SignatureContext context)
}
else
{
+ ModuleToken token = context.GetModuleTokenForType((EcmaType)typeDesc);
+ EmitModuleOverride(token.Module, context);
EmitElementType(CorElementType.ELEMENT_TYPE_CLASS);
- EmitTypeToken((EcmaType)typeDesc, context);
+ EmitToken(token.Token);
}
return;
case TypeFlags.ValueType:
case TypeFlags.Nullable:
case TypeFlags.Enum:
- EmitElementType(CorElementType.ELEMENT_TYPE_VALUETYPE);
- EmitTypeToken((EcmaType)typeDesc, context);
- return;
+ {
+ ModuleToken token = context.GetModuleTokenForType((EcmaType)typeDesc);
+ EmitModuleOverride(token.Module, context);
+ EmitElementType(CorElementType.ELEMENT_TYPE_VALUETYPE);
+ EmitToken(token.Token);
+ return;
+ }
default:
throw new NotImplementedException();
}
}
+ private void EmitModuleOverride(EcmaModule module, SignatureContext context)
+ {
+ if (module != context.LocalContext)
+ {
+ EmitElementType(CorElementType.ELEMENT_TYPE_MODULE_ZAPSIG);
+ uint moduleIndex = (uint)context.Resolver.GetModuleIndex(module);
+ EmitUInt(moduleIndex);
+ }
+ }
+
private void EmitTypeToken(EcmaType type, SignatureContext context)
{
ModuleToken token = context.GetModuleTokenForType(type);
@@ -395,7 +411,7 @@ public void EmitMethodSignature(
{
if (methodToken.IsNull)
{
- methodToken = context.GetModuleTokenForMethod(method.GetTypicalMethodDefinition());
+ methodToken = context.GetModuleTokenForMethod(method);
}
switch (methodToken.TokenType)
{
@@ -462,21 +478,17 @@ private void EmitMethodSpecificationSignature(MethodDesc method, ModuleToken met
MethodSpecification methodSpecification = methodToken.MetadataReader.GetMethodSpecification((MethodSpecificationHandle)methodToken.Handle);
methodToken = new ModuleToken(methodToken.Module, methodSpecification.Method);
}
- else
- {
- throw new NotImplementedException();
- }
}
}
if (methodToken.IsNull && !enforceDefEncoding)
{
- methodToken = context.GetModuleTokenForMethod(method.GetMethodDefinition(), throwIfNotFound: false);
+ methodToken = context.GetModuleTokenForMethod(method, throwIfNotFound: false);
}
if (methodToken.IsNull)
{
flags |= (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_OwnerType;
- methodToken = context.GetModuleTokenForMethod(method.GetTypicalMethodDefinition());
+ methodToken = context.GetModuleTokenForMethod(method);
}
if (method.OwningType.HasInstantiation)
@@ -582,6 +594,21 @@ public ObjectNode.ObjectData ToObjectData()
{
return _builder.ToObjectData();
}
+
+ public SignatureContext EmitFixup(ReadyToRunCodegenNodeFactory factory, ReadyToRunFixupKind fixupKind, EcmaModule targetModule, SignatureContext outerContext)
+ {
+ if (targetModule == outerContext.LocalContext)
+ {
+ EmitByte((byte)fixupKind);
+ return outerContext;
+ }
+ else
+ {
+ EmitByte((byte)(fixupKind | ReadyToRunFixupKind.READYTORUN_FIXUP_ModuleOverride));
+ EmitUInt((uint)factory.ManifestMetadataTable.ModuleToIndex(targetModule));
+ return outerContext.InnerContext(targetModule);
+ }
+ }
}
internal class ArraySignatureBuilder : SignatureBuilder
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/SignatureContext.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/SignatureContext.cs
index c185ed17ee8..667b4ef76f9 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/SignatureContext.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/SignatureContext.cs
@@ -15,26 +15,73 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
public class SignatureContext
{
- private readonly ModuleTokenResolver _resolver;
+ ///
+ /// Context module used for the signature. Whenever a part of the signature
+ /// needs to encode an entity external to the context module, it muse use
+ /// an ELEMENT_TYPE_MODULE_ZAPSIG module override.
+ ///
+ public readonly EcmaModule GlobalContext;
- public SignatureContext(ModuleTokenResolver resolver)
+ ///
+ /// Local context changes during recursive descent while encoding the signature.
+ ///
+ public readonly EcmaModule LocalContext;
+
+ ///
+ /// Resolver used to back-translate types and fields to tokens.
+ ///
+ public readonly ModuleTokenResolver Resolver;
+
+ public SignatureContext(EcmaModule context, ModuleTokenResolver resolver)
+ {
+ GlobalContext = context;
+ LocalContext = context;
+ Resolver = resolver;
+ }
+
+ private SignatureContext(EcmaModule globalContext, EcmaModule localContext, ModuleTokenResolver resolver)
+ {
+ GlobalContext = globalContext;
+ LocalContext = localContext;
+ Resolver = resolver;
+ }
+
+ public SignatureContext InnerContext(EcmaModule innerContext)
+ {
+ return new SignatureContext(GlobalContext, innerContext, Resolver);
+ }
+
+ public EcmaModule GetTargetModule(TypeDesc type)
+ {
+ if (type.IsPrimitive || type.IsString || type.IsObject)
+ {
+ return LocalContext;
+ }
+ if (type.GetTypeDefinition() is EcmaType ecmaType)
+ {
+ return GetModuleTokenForType(ecmaType).Module;
+ }
+ return LocalContext;
+ }
+
+ public EcmaModule GetTargetModule(FieldDesc field)
{
- _resolver = resolver;
+ return GetTargetModule(field.OwningType);
}
public ModuleToken GetModuleTokenForType(EcmaType type, bool throwIfNotFound = true)
{
- return _resolver.GetModuleTokenForType(type, throwIfNotFound);
+ return Resolver.GetModuleTokenForType(type, throwIfNotFound);
}
public ModuleToken GetModuleTokenForMethod(MethodDesc method, bool throwIfNotFound = true)
{
- return _resolver.GetModuleTokenForMethod(method, throwIfNotFound);
+ return Resolver.GetModuleTokenForMethod(method, throwIfNotFound);
}
public ModuleToken GetModuleTokenForField(FieldDesc field, bool throwIfNotFound = true)
{
- return _resolver.GetModuleTokenForField(field, throwIfNotFound);
+ return Resolver.GetModuleTokenForField(field, throwIfNotFound);
}
}
}
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/StringImport.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/StringImport.cs
index f89f65cab78..4374b489333 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/StringImport.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/StringImport.cs
@@ -14,8 +14,8 @@ public class StringImport : Import
private int _definitionOffset;
- public StringImport(ImportSectionNode table, ModuleToken token)
- : base(table, new StringImportSignature(token))
+ public StringImport(ImportSectionNode table, ModuleToken token, SignatureContext signatureContext)
+ : base(table, new StringImportSignature(token, signatureContext))
{
_token = token;
}
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/StringImportSignature.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/StringImportSignature.cs
index 15ac93c05d1..f15cdabd072 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/StringImportSignature.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/StringImportSignature.cs
@@ -11,9 +11,12 @@ public class StringImportSignature : Signature
{
private readonly ModuleToken _token;
- public StringImportSignature(ModuleToken token)
+ private readonly SignatureContext _signatureContext;
+
+ public StringImportSignature(ModuleToken token, SignatureContext signatureContext)
{
_token = token;
+ _signatureContext = signatureContext;
}
public override int ClassCode => 324832559;
@@ -24,8 +27,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
ObjectDataSignatureBuilder dataBuilder = new ObjectDataSignatureBuilder();
dataBuilder.AddSymbol(this);
- // TODO: module override for external module strings
- dataBuilder.EmitByte((byte)ReadyToRunFixupKind.READYTORUN_FIXUP_StringHandle);
+ dataBuilder.EmitFixup(r2rFactory, ReadyToRunFixupKind.READYTORUN_FIXUP_StringHandle, _token.Module, _signatureContext);
dataBuilder.EmitUInt(_token.TokenRid);
return dataBuilder.ToObjectData();
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs
index 01772b5d1ae..dca54e1dde6 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs
@@ -4,9 +4,9 @@
using System;
-using Internal.JitInterface;
using Internal.Text;
using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
@@ -36,8 +36,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
dataBuilder.AddSymbol(this);
- dataBuilder.EmitByte((byte)_fixupKind);
- dataBuilder.EmitTypeSignature(_typeDesc, _signatureContext);
+ EcmaModule targetModule = _signatureContext.GetTargetModule(_typeDesc);
+ SignatureContext innerContext = dataBuilder.EmitFixup(r2rFactory, _fixupKind, targetModule, _signatureContext);
+ dataBuilder.EmitTypeSignature(_typeDesc, innerContext);
}
return dataBuilder.ToObjectData();
@@ -46,7 +47,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix);
- sb.Append($@"TypeFixupSignature({_fixupKind.ToString()}): {_typeDesc.ToString()}");
+ sb.Append($@"TypeFixupSignature({_fixupKind.ToString()}): ");
+ sb.Append(nameMangler.GetMangledTypeName(_typeDesc));
}
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs
index fff772a53be..9722c4deb6d 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs
@@ -61,6 +61,8 @@ public ReadyToRunCodegenNodeFactory(
public InstanceEntryPointTableNode InstanceEntryPointTable;
+ public ManifestMetadataTableNode ManifestMetadataTable;
+
public TypesTableNode TypesTable;
public ImportSectionsTableNode ImportSectionsTable;
@@ -337,13 +339,18 @@ public override void AttachToDependencyGraph(DependencyAnalyzerBase
MethodEntryPointTable = new MethodEntryPointTableNode(Target);
Header.Add(Internal.Runtime.ReadyToRunSectionType.MethodDefEntryPoints, MethodEntryPointTable, MethodEntryPointTable);
+ ManifestMetadataTable = new ManifestMetadataTableNode(InputModuleContext.GlobalContext);
+ Header.Add(Internal.Runtime.ReadyToRunSectionType.ManifestMetadata, ManifestMetadataTable, ManifestMetadataTable);
+
+ Resolver.SetModuleIndexLookup(ManifestMetadataTable.ModuleToIndex);
+
InstanceEntryPointTable = new InstanceEntryPointTableNode(Target);
Header.Add(Internal.Runtime.ReadyToRunSectionType.InstanceMethodEntryPoints, InstanceEntryPointTable, InstanceEntryPointTable);
TypesTable = new TypesTableNode(Target);
Header.Add(Internal.Runtime.ReadyToRunSectionType.AvailableTypes, TypesTable, TypesTable);
- ImportSectionsTable = new ImportSectionsTableNode(Target);
+ ImportSectionsTable = new ImportSectionsTableNode(this);
Header.Add(Internal.Runtime.ReadyToRunSectionType.ImportSections, ImportSectionsTable, ImportSectionsTable.StartSymbol);
DebugInfoTable = new DebugInfoTableNode(Target);
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs
index 0f7427c7d3d..87b9f1485f2 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs
@@ -27,11 +27,11 @@ public ReadyToRunSymbolNodeFactory(ReadyToRunCodegenNodeFactory codegenNodeFacto
private readonly Dictionary _importStrings = new Dictionary();
- public ISymbolNode StringLiteral(ModuleToken token)
+ public ISymbolNode StringLiteral(ModuleToken token, SignatureContext signatureContext)
{
if (!_importStrings.TryGetValue(token, out ISymbolNode stringNode))
{
- stringNode = new StringImport(_codegenNodeFactory.StringImports, token);
+ stringNode = new StringImport(_codegenNodeFactory.StringImports, token, signatureContext);
_importStrings.Add(token, stringNode);
}
return stringNode;
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/ILCompiler.ReadyToRun/src/Compiler/ReadyToRunCodegenCompilationBuilder.cs
index 1ad1a0de9c6..4433b8d0353 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/ReadyToRunCodegenCompilationBuilder.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/ReadyToRunCodegenCompilationBuilder.cs
@@ -79,7 +79,7 @@ public override ICompilation ToCompilation()
var interopStubManager = new EmptyInteropStubManager(_compilationGroup, _context, new InteropStateManager(_context.GeneratedAssembly));
ModuleTokenResolver moduleTokenResolver = new ModuleTokenResolver(_compilationGroup, _context);
- SignatureContext signatureContext = new SignatureContext(moduleTokenResolver);
+ SignatureContext signatureContext = new SignatureContext(_inputModule, moduleTokenResolver);
ReadyToRunCodegenNodeFactory factory = new ReadyToRunCodegenNodeFactory(
_context,
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/ReadyToRunSingleAssemblyCompilationModuleGroup.cs b/src/ILCompiler.ReadyToRun/src/Compiler/ReadyToRunSingleAssemblyCompilationModuleGroup.cs
index 52b61b10ae1..e70764102b5 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/ReadyToRunSingleAssemblyCompilationModuleGroup.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/ReadyToRunSingleAssemblyCompilationModuleGroup.cs
@@ -2,10 +2,10 @@
// 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 System.Diagnostics;
-using ILCompiler.DependencyAnalysis;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
@@ -14,26 +14,25 @@ namespace ILCompiler
public class ReadyToRunSingleAssemblyCompilationModuleGroup : CompilationModuleGroup
{
private HashSet _compilationModuleSet;
+ private HashSet _versionBubbleModuleSet;
- public ReadyToRunSingleAssemblyCompilationModuleGroup(TypeSystemContext context, IEnumerable compilationModuleSet)
+ public ReadyToRunSingleAssemblyCompilationModuleGroup(
+ TypeSystemContext context,
+ IEnumerable compilationModuleSet,
+ IEnumerable versionBubbleModuleSet)
{
_compilationModuleSet = new HashSet(compilationModuleSet);
// The fake assembly that holds compiler generated types is part of the compilation.
_compilationModuleSet.Add(context.GeneratedAssembly);
+
+ _versionBubbleModuleSet = new HashSet(versionBubbleModuleSet);
+ _versionBubbleModuleSet.UnionWith(_compilationModuleSet);
}
public sealed override bool ContainsType(TypeDesc type)
{
- if (type is EcmaType ecmaType)
- {
- return IsModuleInCompilationGroup(ecmaType.EcmaModule);
- }
- if (type is InstantiatedType instantiatedType)
- {
- return ContainsType(instantiatedType.GetTypeDefinition());
- }
- return true;
+ return type.GetTypeDefinition() is EcmaType ecmaType && IsModuleInCompilationGroup(ecmaType.EcmaModule);
}
public sealed override bool ContainsTypeDictionary(TypeDesc type)
@@ -206,11 +205,27 @@ private bool ContainsTypeLayoutUncached(TypeDesc type, HashSet recursi
return true;
}
+ public override bool VersionsWithType(TypeDesc typeDesc)
+ {
+ return typeDesc.GetTypeDefinition() is EcmaType ecmaType &&
+ _versionBubbleModuleSet.Contains(ecmaType.EcmaModule);
+ }
+
+ public override bool VersionsWithMethodBody(MethodDesc method)
+ {
+ return VersionsWithType(method.OwningType);
+ }
+
public override bool CanInline(MethodDesc callerMethod, MethodDesc calleeMethod)
{
- // Allow inlining if the target method is within the same version bubble
- return ContainsMethodBody(calleeMethod, unboxingStub: false) ||
- calleeMethod.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute");
+ // Allow inlining if the caller is within the current version bubble
+ // (because otherwise we may not be able to encode its tokens)
+ // and if the callee is either in the same version bubble or is marked as non-versionable.
+ bool canInline = VersionsWithMethodBody(callerMethod) &&
+ (VersionsWithMethodBody(calleeMethod) ||
+ calleeMethod.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute"));
+
+ return canInline;
}
}
}
diff --git a/src/ILCompiler.ReadyToRun/src/Compiler/RuntimeDeterminedTypeHelper.cs b/src/ILCompiler.ReadyToRun/src/Compiler/RuntimeDeterminedTypeHelper.cs
index dc1ad99b9be..a52d7dc818b 100644
--- a/src/ILCompiler.ReadyToRun/src/Compiler/RuntimeDeterminedTypeHelper.cs
+++ b/src/ILCompiler.ReadyToRun/src/Compiler/RuntimeDeterminedTypeHelper.cs
@@ -151,109 +151,5 @@ public static int GetHashCode(FieldDesc field)
{
return unchecked(GetHashCode(field.OwningType) + 97 * GetHashCode(field.FieldType) + 31 * field.Name.GetHashCode());
}
-
- public static void WriteTo(Instantiation instantiation, Utf8StringBuilder sb)
- {
- sb.Append("<");
- for (int typeArgIndex = 0; typeArgIndex < instantiation.Length; typeArgIndex++)
- {
- if (typeArgIndex != 0)
- {
- sb.Append(", ");
- }
- WriteTo(instantiation[typeArgIndex], sb);
- }
- sb.Append(">");
- }
-
- public static void WriteTo(TypeDesc type, Utf8StringBuilder sb)
- {
- if (type is RuntimeDeterminedType runtimeDeterminedType)
- {
- switch (runtimeDeterminedType.RuntimeDeterminedDetailsType.Kind)
- {
- case GenericParameterKind.Type:
- sb.Append("T");
- break;
-
- case GenericParameterKind.Method:
- sb.Append("M");
- break;
-
- default:
- throw new NotImplementedException();
- }
- sb.Append(runtimeDeterminedType.RuntimeDeterminedDetailsType.Index.ToString());
- }
- else if (type is InstantiatedType instantiatedType)
- {
- sb.Append(instantiatedType.GetTypeDefinition().ToString());
- WriteTo(instantiatedType.Instantiation, sb);
- }
- else if (type is ArrayType arrayType)
- {
- WriteTo(arrayType.ElementType, sb);
- sb.Append("[");
- switch (arrayType.Rank)
- {
- case 0:
- break;
- case 1:
- sb.Append("*");
- break;
- default:
- sb.Append(new String(',', arrayType.Rank - 1));
- break;
- }
- sb.Append("]");
- }
- else if (type is ByRefType byRefType)
- {
- WriteTo(byRefType.ParameterType, sb);
- sb.Append("&");
- }
- else if (type is PointerType pointerType)
- {
- WriteTo(pointerType.ParameterType, sb);
- sb.Append("*");
- }
- else
- {
- Debug.Assert(type is DefType);
- sb.Append(type.ToString());
- }
- }
-
- public static void WriteTo(MethodDesc method, Utf8StringBuilder sb)
- {
- WriteTo(method.Signature.ReturnType, sb);
- sb.Append(" ");
- WriteTo(method.OwningType, sb);
- sb.Append(".");
- sb.Append(method.Name);
- if (method.HasInstantiation)
- {
- WriteTo(method.Instantiation, sb);
- }
- sb.Append("(");
- for (int argIndex = 0; argIndex < method.Signature.Length; argIndex++)
- {
- if (argIndex != 0)
- {
- sb.Append(", ");
- }
- WriteTo(method.Signature[argIndex], sb);
- }
- sb.Append(")");
- }
-
- public static void WriteTo(FieldDesc field, Utf8StringBuilder sb)
- {
- WriteTo(field.FieldType, sb);
- sb.Append(" ");
- WriteTo(field.OwningType, sb);
- sb.Append(".");
- sb.Append(field.Name);
- }
}
}
diff --git a/src/ILCompiler.ReadyToRun/src/ILCompiler.ReadyToRun.csproj b/src/ILCompiler.ReadyToRun/src/ILCompiler.ReadyToRun.csproj
index 302bc2f30f1..c0cd01a7c5f 100644
--- a/src/ILCompiler.ReadyToRun/src/ILCompiler.ReadyToRun.csproj
+++ b/src/ILCompiler.ReadyToRun/src/ILCompiler.ReadyToRun.csproj
@@ -54,6 +54,7 @@
+
diff --git a/src/ILCompiler.ReadyToRun/src/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/ILCompiler.ReadyToRun/src/JitInterface/CorInfoImpl.ReadyToRun.cs
index 4e6870b43cc..96ae6ae9f18 100644
--- a/src/ILCompiler.ReadyToRun/src/JitInterface/CorInfoImpl.ReadyToRun.cs
+++ b/src/ILCompiler.ReadyToRun/src/JitInterface/CorInfoImpl.ReadyToRun.cs
@@ -106,14 +106,11 @@ unsafe partial class CorInfoImpl
///
private readonly EcmaModule _tokenContext;
- private readonly SignatureContext _signatureContext;
-
public CorInfoImpl(ReadyToRunCodegenCompilation compilation, EcmaModule tokenContext, JitConfigProvider jitConfig)
: this(jitConfig)
{
_compilation = compilation;
_tokenContext = tokenContext;
- _signatureContext = new SignatureContext(_compilation.NodeFactory.Resolver);
}
public void CompileMethod(IReadyToRunMethodCodeNode methodCodeNodeNeedingCode)
@@ -180,11 +177,17 @@ private void ComputeLookup(ref CORINFO_RESOLVED_TOKEN pResolvedToken, object ent
targetEntity = new MethodWithToken(methodDesc, new ModuleToken(_tokenContext, pResolvedToken.token));
}
lookup.lookupKind.needsRuntimeLookup = false;
- ISymbolNode constLookup = _compilation.SymbolNodeFactory.ComputeConstantLookup(helperId, targetEntity, _signatureContext);
+ ISymbolNode constLookup = _compilation.SymbolNodeFactory.ComputeConstantLookup(helperId, targetEntity, GetSignatureContext());
lookup.constLookup = CreateConstLookupToSymbol(constLookup);
}
}
+ private SignatureContext GetSignatureContext()
+ {
+ // TODO: this will need changing when compiling multiple input MSIL modules into a single PE executable
+ return _compilation.NodeFactory.InputModuleContext;
+ }
+
private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_LOOKUP_KIND pGenericLookupKind, CorInfoHelpFunc id, ref CORINFO_CONST_LOOKUP pLookup)
{
switch (id)
@@ -196,7 +199,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
return false;
- pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewHelper, type, _signatureContext));
+ pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewHelper, type, GetSignatureContext()));
}
break;
case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEWARR_1:
@@ -206,7 +209,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
return false;
- pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewArr1, type, _signatureContext));
+ pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewArr1, type, GetSignatureContext()));
}
break;
case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_ISINSTANCEOF:
@@ -219,7 +222,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
if (type.IsNullable)
type = type.Instantiation[0];
- pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type, _signatureContext));
+ pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type, GetSignatureContext()));
}
break;
case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_CHKCAST:
@@ -232,7 +235,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
if (type.IsNullable)
type = type.Instantiation[0];
- pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CastClass, type, _signatureContext));
+ pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CastClass, type, GetSignatureContext()));
}
break;
case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE:
@@ -241,7 +244,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
return false;
- pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CctorTrigger, type, _signatureContext));
+ pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CctorTrigger, type, GetSignatureContext()));
}
break;
case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_HANDLE:
@@ -267,7 +270,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
helperArg,
constrainedType,
methodContext,
- _signatureContext);
+ GetSignatureContext());
pLookup = CreateConstLookupToSymbol(helper);
}
break;
@@ -291,7 +294,7 @@ private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetM
pLookup.lookupKind.needsRuntimeLookup = false;
pLookup.constLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.DelegateCtor(
- delegateTypeDesc, targetMethod, new ModuleToken(_tokenContext, (mdToken)pTargetMethod.token), _signatureContext));
+ delegateTypeDesc, targetMethod, new ModuleToken(_tokenContext, (mdToken)pTargetMethod.token), GetSignatureContext()));
}
private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum)
@@ -629,7 +632,7 @@ private bool canTailCall(CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUC
private InfoAccessType constructStringLiteral(CORINFO_MODULE_STRUCT_* module, mdToken metaTok, ref void* ppValue)
{
- ISymbolNode stringObject = _compilation.SymbolNodeFactory.StringLiteral(new ModuleToken(_tokenContext, metaTok));
+ ISymbolNode stringObject = _compilation.SymbolNodeFactory.StringLiteral(new ModuleToken(_tokenContext, metaTok), GetSignatureContext());
ppValue = (void*)ObjectToHandle(stringObject);
return InfoAccessType.IAT_PPVALUE;
}
@@ -809,7 +812,7 @@ private void ceeInfoGetCallInfo(
TypeDesc type = HandleToObject(pResolvedToken.hClass);
callerMethod = HandleToObject(callerHandle);
- if (!_compilation.NodeFactory.CompilationModuleGroup.ContainsMethodBody(callerMethod, unboxingStub: false))
+ if (!_compilation.NodeFactory.CompilationModuleGroup.VersionsWithMethodBody(callerMethod))
{
// We must abort inline attempts calling from outside of the version bubble being compiled
// because we have no way to remap the token relative to the external module to the current version bubble.
@@ -961,8 +964,8 @@ private void ceeInfoGetCallInfo(
// we have to apply more restrictive rules
// These rules are related to the "inlining rules" as far as the
// boundaries of a version bubble are concerned.
- if (!_compilation.NodeFactory.CompilationModuleGroup.ContainsMethodBody(callerMethod, unboxingStub: false) ||
- !_compilation.NodeFactory.CompilationModuleGroup.ContainsMethodBody(targetMethod, unboxingStub: false))
+ if (!_compilation.NodeFactory.CompilationModuleGroup.VersionsWithMethodBody(callerMethod) ||
+ !_compilation.NodeFactory.CompilationModuleGroup.VersionsWithMethodBody(targetMethod))
{
// For version resiliency we won't de-virtualize all final/sealed method calls. Because during a
// servicing event it is legal to unseal a method or type.
@@ -1117,7 +1120,7 @@ private void ceeInfoGetCallInfo(
private bool MethodInSystemVersionBubble(MethodDesc method)
{
- return _compilation.NodeFactory.CompilationModuleGroup.ContainsMethodBody(method, unboxingStub: false) &&
+ return _compilation.NodeFactory.CompilationModuleGroup.VersionsWithMethodBody(method) &&
method.OwningType.GetTypeDefinition().GetClosestDefType() is MetadataType metadataType &&
metadataType.Module == _compilation.TypeSystemContext.SystemModule;
}
@@ -1167,7 +1170,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
pResult->codePointerOrStubLookup.constLookup = CreateConstLookupToSymbol(
_compilation.SymbolNodeFactory.InterfaceDispatchCell(targetMethod,
new ModuleToken(callerModule, (mdToken)pResolvedToken.token),
- _signatureContext,
+ GetSignatureContext(),
isUnboxingStub: false,
_compilation.NameMangler.GetMangledMethodName(MethodBeingCompiled).ToString()));
}
@@ -1194,7 +1197,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
new ModuleToken(callerModule, pResolvedToken.token),
isUnboxingStub: false,
isInstantiatingStub: useInstantiatingStub,
- _signatureContext));
+ GetSignatureContext()));
}
break;
@@ -1210,7 +1213,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
pResult->codePointerOrStubLookup.constLookup = CreateConstLookupToSymbol(
_compilation.NodeFactory.DynamicHelperCell(
new MethodWithToken(targetMethod, new ModuleToken(callerModule, pResolvedToken.token)),
- _signatureContext));
+ GetSignatureContext()));
Debug.Assert(!pResult->sig.hasTypeArg());
}
@@ -1238,14 +1241,14 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
pResult->instParamLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(
ReadyToRunHelperId.MethodDictionary,
new MethodWithToken(targetMethod, new ModuleToken(callerModule, pResolvedToken.token)),
- signatureContext: _signatureContext));
+ signatureContext: GetSignatureContext()));
}
else
{
pResult->instParamLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(
ReadyToRunHelperId.TypeDictionary,
exactType,
- signatureContext: _signatureContext));
+ signatureContext: GetSignatureContext()));
}
}
}
@@ -1271,7 +1274,7 @@ private void ComputeRuntimeLookupForSharedGenericToken(
pResult.indirections = CORINFO.USEHELPER;
MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext);
- TypeDesc contextType = contextMethod.OwningType;
+ TypeDesc contextType = typeFromContext(pResolvedToken.tokenContext);
// Do not bother computing the runtime lookup if we are inlining. The JIT is going
// to abort the inlining attempt anyway.
@@ -1474,21 +1477,21 @@ private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool
symbolNode = _compilation.SymbolNodeFactory.ReadyToRunHelper(
ReadyToRunHelperId.TypeHandle,
HandleToObject(pResolvedToken.hClass),
- _signatureContext);
+ GetSignatureContext());
break;
case CorInfoGenericHandleType.CORINFO_HANDLETYPE_METHOD:
symbolNode = _compilation.SymbolNodeFactory.ReadyToRunHelper(
ReadyToRunHelperId.MethodHandle,
new MethodWithToken(HandleToObject(pResolvedToken.hMethod), new ModuleToken(_tokenContext, pResolvedToken.token)),
- _signatureContext);
+ GetSignatureContext());
break;
case CorInfoGenericHandleType.CORINFO_HANDLETYPE_FIELD:
symbolNode = _compilation.SymbolNodeFactory.ReadyToRunHelper(
ReadyToRunHelperId.FieldHandle,
HandleToObject(pResolvedToken.hField),
- _signatureContext);
+ GetSignatureContext());
break;
default:
@@ -1514,7 +1517,7 @@ private bool IsLayoutFixedInCurrentVersionBubble(TypeDesc type)
return true;
}
- if (!_compilation.NodeFactory.CompilationModuleGroup.ContainsType(type))
+ if (!_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(type))
{
if (!type.IsValueType)
{
@@ -1579,7 +1582,7 @@ private bool HasLayoutMetadata(TypeDesc type)
///
private void PreventRecursiveFieldInlinesOutsideVersionBubble(FieldDesc field, MethodDesc callerMethod)
{
- if (!_compilation.NodeFactory.CompilationModuleGroup.ContainsMethodBody(callerMethod, unboxingStub: false))
+ if (!_compilation.NodeFactory.CompilationModuleGroup.VersionsWithMethodBody(callerMethod))
{
// Prevent recursive inline attempts where an inlined method outside of the version bubble is
// referencing fields outside the version bubble.
@@ -1609,7 +1612,7 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult,
// ENCODE_FIELD_OFFSET
pResult->offset = 0;
pResult->fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE_WITH_BASE;
- pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldOffset(field, _signatureContext));
+ pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldOffset(field, GetSignatureContext()));
}
}
else if (pMT.IsValueType)
@@ -1629,7 +1632,7 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult,
// ENCODE_FIELD_OFFSET
pResult->offset = 0;
pResult->fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE_WITH_BASE;
- pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldOffset(field, _signatureContext));
+ pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldOffset(field, GetSignatureContext()));
}
else
{
@@ -1638,7 +1641,7 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult,
// ENCODE_FIELD_BASE_OFFSET
pResult->offset -= (uint)pMT.BaseType.InstanceByteCount.AsInt;
pResult->fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE_WITH_BASE;
- pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldBaseOffset(field.OwningType, _signatureContext));
+ pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldBaseOffset(field.OwningType, GetSignatureContext()));
}
}
}
diff --git a/src/ILCompiler/src/Program.cs b/src/ILCompiler/src/Program.cs
index 44c82e87a94..b69e7872821 100644
--- a/src/ILCompiler/src/Program.cs
+++ b/src/ILCompiler/src/Program.cs
@@ -402,16 +402,38 @@ private int Run(string[] args)
foreach (var inputFile in typeSystemContext.InputFilePaths)
{
EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);
-
compilationRoots.Add(new ReadyToRunRootProvider(module));
inputModules.Add(module);
+
if (!_isInputVersionBubble)
{
break;
}
}
- compilationGroup = new ReadyToRunSingleAssemblyCompilationModuleGroup(typeSystemContext, inputModules);
+
+ List versionBubbleModules = new List();
+ if (_isInputVersionBubble)
+ {
+ // In large version bubble mode add reference paths to the compilation group
+ foreach (string referenceFile in _referenceFilePaths.Values)
+ {
+ try
+ {
+ // Currently SimpleTest.targets has no easy way to filter out non-managed assemblies
+ // from the reference list.
+ EcmaModule module = typeSystemContext.GetModuleFromPath(referenceFile);
+ versionBubbleModules.Add(module);
+ }
+ catch (BadImageFormatException ex)
+ {
+ Console.WriteLine("Warning: cannot open reference assembly '{0}': {1}", referenceFile, ex.Message);
+ }
+ }
+ }
+
+ compilationGroup = new ReadyToRunSingleAssemblyCompilationModuleGroup(
+ typeSystemContext, inputModules, versionBubbleModules);
}
else if (_multiFile)
{
diff --git a/src/JitInterface/src/CorInfoImpl.cs b/src/JitInterface/src/CorInfoImpl.cs
index d5f311400ff..cc70ce12321 100644
--- a/src/JitInterface/src/CorInfoImpl.cs
+++ b/src/JitInterface/src/CorInfoImpl.cs
@@ -984,7 +984,7 @@ private void resolveToken(ref CORINFO_RESOLVED_TOKEN pResolvedToken)
#if READYTORUN
TypeDesc owningType = methodIL.OwningMethod.GetTypicalMethodDefinition().OwningType;
EcmaModule tokenContextToRecord = null;
- if (_compilation.NodeFactory.CompilationModuleGroup.ContainsType(owningType) &&
+ if (_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(owningType) &&
owningType is EcmaType owningEcmaType)
{
tokenContextToRecord = owningEcmaType.EcmaModule;
@@ -2150,7 +2150,7 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET
// Static fields outside of the version bubble need to be accessed using the ENCODE_FIELD_ADDRESS
// helper in accordance with ZapInfo::getFieldInfo in CoreCLR.
- pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldAddress(field, _signatureContext));
+ pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldAddress(field, GetSignatureContext()));
pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE;
@@ -2164,7 +2164,7 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET
{
pResult->fieldLookup = CreateConstLookupToSymbol(
#if READYTORUN
- _compilation.SymbolNodeFactory.ReadyToRunHelper(helperId, field.OwningType, _signatureContext)
+ _compilation.SymbolNodeFactory.ReadyToRunHelper(helperId, field.OwningType, GetSignatureContext())
#else
_compilation.NodeFactory.ReadyToRunHelper(helperId, field.OwningType)
#endif