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