public IEnumerable<DependencyListEntry> InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation) { switch (_id) { case ReadyToRunHelperId.GetGCStaticBase: case ReadyToRunHelperId.GetThreadStaticBase: { // If the type has a lazy static constructor, we also need the non-GC static base // because that's where the class constructor context is. TypeDesc type = (TypeDesc)_target; if (factory.TypeSystemContext.HasLazyStaticConstructor(type)) { return new[] { new DependencyListEntry( factory.GenericLookup.TypeNonGCStaticBase(type).GetTarget(factory, typeInstantiation, methodInstantiation), "Dictionary dependency"), new DependencyListEntry( _lookupSignature.GetTarget(factory, typeInstantiation, methodInstantiation), "Dictionary dependency") }; } } break; } // All other generic lookups just depend on the thing they point to return new[] { new DependencyListEntry( _lookupSignature.GetTarget(factory, typeInstantiation, methodInstantiation), "Dictionary dependency") }; }
/// <summary> /// Constructs a new instance of <see cref="DelegateCreationInfo"/> set up to construct a delegate of type /// '<paramref name="delegateType"/>' pointing to '<paramref name="targetMethod"/>'. /// </summary> public static DelegateCreationInfo Create(TypeDesc delegateType, MethodDesc targetMethod, NodeFactory factory) { var context = (CompilerTypeSystemContext)delegateType.Context; var systemDelegate = targetMethod.Context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType; int paramCountTargetMethod = targetMethod.Signature.Length; if (!targetMethod.Signature.IsStatic) { paramCountTargetMethod++; } DelegateInfo delegateInfo = context.GetDelegateInfo(delegateType.GetTypeDefinition()); int paramCountDelegateClosed = delegateInfo.Signature.Length + 1; bool closed = false; if (paramCountDelegateClosed == paramCountTargetMethod) { closed = true; } else { Debug.Assert(paramCountDelegateClosed == paramCountTargetMethod + 1); } if (targetMethod.Signature.IsStatic) { MethodDesc invokeThunk; if (!closed) { // Open delegate to a static method invokeThunk = delegateInfo.Thunks[DelegateThunkKind.OpenStaticThunk]; } else { // Closed delegate to a static method (i.e. delegate to an extension method that locks the first parameter) invokeThunk = delegateInfo.Thunks[DelegateThunkKind.ClosedStaticThunk]; } var instantiatedDelegateType = delegateType as InstantiatedType; if (instantiatedDelegateType != null) invokeThunk = context.GetMethodForInstantiatedType(invokeThunk, instantiatedDelegateType); // We use InitializeClosedStaticThunk for both because RyuJIT generates same code for both, // but passes null as the first parameter for the open one. return new DelegateCreationInfo( factory.MethodEntrypoint(systemDelegate.GetKnownMethod("InitializeClosedStaticThunk", null)), factory.MethodEntrypoint(targetMethod), factory.MethodEntrypoint(invokeThunk)); } else { if (!closed) throw new NotImplementedException("Open instance delegates"); bool useUnboxingStub = targetMethod.OwningType.IsValueType; return new DelegateCreationInfo( factory.MethodEntrypoint(systemDelegate.GetKnownMethod("InitializeClosedInstance", null)), factory.MethodEntrypoint(targetMethod, useUnboxingStub)); } }
public ISymbolNode GetGCStaticEETypeNode(NodeFactory context) { // TODO Replace with better gcDesc computation algorithm when we add gc handling to the type system // TODO This logic should be shared with GCStaticsNode. bool[] gcDesc = new bool[_type.ThreadStaticFieldSize / context.Target.PointerSize + 1]; return context.GCStaticEEType(gcDesc); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.DefinedSymbols.Add(this); // // Emit a MethodFixupCell struct // // Address (to be fixed up at runtime) builder.EmitZeroPointer(); // Entry point name if (factory.Target.IsWindows && _entryPointName.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { // Windows-specific ordinal import // CLR-compatible behavior: Strings that can't be parsed as a signed integer are treated as zero. int entrypointOrdinal; if (!int.TryParse(_entryPointName.Substring(1), out entrypointOrdinal)) entrypointOrdinal = 0; // CLR-compatible behavior: Ordinal imports are 16-bit on Windows. Discard rest of the bits. builder.EmitNaturalInt((ushort)entrypointOrdinal); } else { // Import by name builder.EmitPointerReloc(factory.ConstantUtf8String(_entryPointName)); } // Module fixup cell builder.EmitPointerReloc(factory.PInvokeModuleFixup(_moduleName)); return builder.ToObjectData(); }
public ExternEETypeSymbolNode(NodeFactory factory, TypeDesc type) : base("__EEType_" + NodeFactory.NameMangler.GetMangledTypeName(type)) { _type = type; EETypeNode.CheckCanGenerateEEType(factory, type); }
private static int GetNumberOfBaseSlots(NodeFactory factory, TypeDesc owningType) { int baseSlots = 0; TypeDesc baseType = owningType.BaseType; while (baseType != null) { // Normalize the base type. Necessary to make this work with the lazy vtable slot // concept - if we start with a canonical type, the base type could end up being // something like Base<__Canon, string>. We would get "0 slots used" for weird // base types like this. baseType = baseType.ConvertToCanonForm(CanonicalFormKind.Specific); // For types that have a generic dictionary, the introduced virtual method slots are // prefixed with a pointer to the generic dictionary. if (baseType.HasGenericDictionarySlot()) baseSlots++; IReadOnlyList<MethodDesc> baseVirtualSlots = factory.VTable(baseType).Slots; baseSlots += baseVirtualSlots.Count; baseType = baseType.BaseType; } return baseSlots; }
protected override void OutputRelatedType(NodeFactory factory, ref ObjectDataBuilder objData) { // // Cloned types use the related type field to point via an IAT slot at their true implementation // objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_type)); }
protected Compilation( DependencyAnalyzerBase<NodeFactory> dependencyGraph, NodeFactory nodeFactory, IEnumerable<ICompilationRootProvider> compilationRoots, NameMangler nameMangler, Logger logger) { _dependencyGraph = dependencyGraph; _nodeFactory = nodeFactory; _nameMangler = nameMangler; _logger = logger; _dependencyGraph.ComputeDependencyRoutine += ComputeDependencyNodeDependencies; NodeFactory.AttachToDependencyGraph(_dependencyGraph); // TODO: hacky static field NodeFactory.NameMangler = nameMangler; var rootingService = new RootingServiceProvider(dependencyGraph, nodeFactory); foreach (var rootProvider in compilationRoots) rootProvider.AddCompilationRoots(rootingService); // TODO: use a better owning type for multi-file friendliness _typeGetTypeMethodThunks = new TypeGetTypeMethodThunkCache(TypeSystemContext.SystemModule.GetGlobalModuleType()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.Alignment = factory.Target.PointerSize; if (_sorter != null) _nestedNodesList.Sort(_sorter); builder.DefinedSymbols.Add(_startSymbol); foreach (EmbeddedObjectNode node in _nestedNodesList) { if (!relocsOnly) node.Offset = builder.CountBytes; node.EncodeData(ref builder, factory, relocsOnly); if (node is ISymbolNode) { builder.DefinedSymbols.Add((ISymbolNode)node); } } _endSymbol.SetSymbolOffset(builder.CountBytes); builder.DefinedSymbols.Add(_endSymbol); ObjectData objData = builder.ToObjectData(); return objData; }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { var builder = new ObjectDataBuilder(factory); // These need to be aligned the same as methods because they show up in same contexts builder.RequireAlignment(factory.Target.MinimumFunctionAlignment); builder.DefinedSymbols.Add(this); MethodDesc canonMethod = Method.GetCanonMethodTarget(CanonicalFormKind.Specific); // Pointer to the canonical body of the method builder.EmitPointerReloc(factory.MethodEntrypoint(canonMethod)); // Find out what's the context to use ISymbolNode contextParameter; if (canonMethod.RequiresInstMethodDescArg()) { contextParameter = factory.MethodGenericDictionary(Method); } else { Debug.Assert(canonMethod.RequiresInstMethodTableArg()); // Ask for a constructed type symbol because we need the vtable to get to the dictionary contextParameter = factory.ConstructedTypeSymbol(Method.OwningType); } // The next entry is a pointer to the pointer to the context to be used for the canonical method // TODO: in multi-module, this points to the import cell, and is no longer this weird pointer builder.EmitPointerReloc(factory.Indirection(contextParameter)); return builder.ToObjectData(); }
protected Compilation( DependencyAnalyzerBase<NodeFactory> dependencyGraph, NodeFactory nodeFactory, IEnumerable<ICompilationRootProvider> compilationRoots, NameMangler nameMangler, Logger logger) { _dependencyGraph = dependencyGraph; _nodeFactory = nodeFactory; _nameMangler = nameMangler; _logger = logger; _dependencyGraph.ComputeDependencyRoutine += ComputeDependencyNodeDependencies; NodeFactory.AttachToDependencyGraph(_dependencyGraph); // TODO: hacky static field NodeFactory.NameMangler = nameMangler; var rootingService = new RootingServiceProvider(dependencyGraph, nodeFactory); foreach (var rootProvider in compilationRoots) rootProvider.AddCompilationRoots(rootingService); _typeGetTypeMethodThunks = new TypeGetTypeMethodThunkCache(nodeFactory.CompilationModuleGroup.GeneratedAssembly.GetGlobalModuleType()); PInvokeILProvider = new PInvokeILProvider(new PInvokeILEmitterConfiguration(!nodeFactory.CompilationModuleGroup.IsSingleFileCompilation)); _methodILCache = new ILProvider(PInvokeILProvider); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.Alignment = factory.Target.PointerSize; builder.DefinedSymbols.Add(this); _items.Sort((x, y) => Comparer<int>.Default.Compare((int)x.Id, (int)y.Id)); // ReadyToRunHeader.Magic builder.EmitInt((int)(ReadyToRunHeaderConstants.Signature)); // ReadyToRunHeader.MajorVersion builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMajorVersion)); builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMinorVersion)); // ReadyToRunHeader.Flags builder.EmitInt(0); // ReadyToRunHeader.NumberOfSections var sectionCountReservation = builder.ReserveShort(); // ReadyToRunHeader.EntrySize builder.EmitByte((byte)(8 + 2 * factory.Target.PointerSize)); // ReadyToRunHeader.EntryType builder.EmitByte(1); int count = 0; foreach (var item in _items) { // Skip empty entries if (item.Node.ShouldSkipEmittingObjectNode(factory)) continue; builder.EmitInt((int)item.Id); ModuleInfoFlags flags = 0; if (item.EndSymbol != null) { flags |= ModuleInfoFlags.HasEndPointer; } builder.EmitInt((int)flags); builder.EmitPointerReloc(item.StartSymbol); if (item.EndSymbol != null) { builder.EmitPointerReloc(item.EndSymbol); } else { builder.EmitZeroPointer(); } count++; } builder.EmitShort(sectionCountReservation, checked((short)count)); return builder.ToObjectData(); }
DispatchMapEntry[] BuildDispatchMap(NodeFactory factory) { ArrayBuilder<DispatchMapEntry> dispatchMapEntries = new ArrayBuilder<DispatchMapEntry>(); for (int i = 0; i < _type.RuntimeInterfaces.Length; i++) { var interfaceType = _type.RuntimeInterfaces[i]; Debug.Assert(interfaceType.IsInterface); List<MethodDesc> virtualSlots; factory.VirtualSlots.TryGetValue(interfaceType, out virtualSlots); if (virtualSlots != null) { for (int j = 0; j < virtualSlots.Count; j++) { MethodDesc declMethod = virtualSlots[j]; var implMethod = VirtualFunctionResolution.ResolveInterfaceMethodToVirtualMethodOnType(declMethod, _type.GetClosestMetadataType()); // Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface // dispatch will walk the inheritance chain). if (implMethod != null) { var entry = new DispatchMapEntry(); entry.InterfaceIndex = checked((short)i); entry.InterfaceMethodSlot = checked((short)j); entry.ImplementationMethodSlot = checked((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, implMethod)); dispatchMapEntries.Add(entry); } } } } return dispatchMapEntries.ToArray(); }
/// <summary> /// Given a virtual method decl, return its VTable slot if the method is used on its containing type. /// Return -1 if the virtual method is not used. /// </summary> public static int GetVirtualMethodSlot(NodeFactory factory, MethodDesc method) { // TODO: More efficient lookup of the slot TypeDesc owningType = method.OwningType; int baseSlots = 0; var baseType = owningType.BaseType; while (baseType != null) { List<MethodDesc> baseVirtualSlots; factory.VirtualSlots.TryGetValue(baseType, out baseVirtualSlots); if (baseVirtualSlots != null) baseSlots += baseVirtualSlots.Count; baseType = baseType.BaseType; } List<MethodDesc> virtualSlots = factory.VirtualSlots[owningType]; int methodSlot = -1; for (int slot = 0; slot < virtualSlots.Count; slot++) { if (virtualSlots[slot] == method) { methodSlot = slot; break; } } return methodSlot == -1 ? -1 : baseSlots + methodSlot; }
protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bool relocsOnly) { AddrMode thisPtr = new AddrMode( Register.RegDirect | encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64); encoder.EmitADD(ref thisPtr, (sbyte)factory.Target.PointerSize); encoder.EmitJMP(factory.MethodEntrypoint(_target)); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, new ISymbolNode[] { this }); ObjectDataBuilder builder = new ObjectDataBuilder(factory); foreach (var mappingEntry in factory.MetadataManager.GetTypeDefinitionMapping()) { if (!factory.CompilationModuleGroup.ContainsType(mappingEntry.Entity)) continue; var node = factory.ConstructedTypeSymbol(mappingEntry.Entity) as EETypeNode; if (node.Marked) { // TODO: this format got very inefficient due to not being able to use RVAs // replace with a hash table builder.EmitPointerReloc(node); builder.EmitInt(mappingEntry.MetadataHandle); if (factory.Target.PointerSize == 8) builder.EmitInt(0); // Pad } } _endSymbol.SetSymbolOffset(builder.CountBytes); builder.DefinedSymbols.Add(this); builder.DefinedSymbols.Add(_endSymbol); return builder.ToObjectData(); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { dataBuilder.EmitZeroPointer(); // Sync block DefType systemStringType = factory.TypeSystemContext.GetWellKnownType(WellKnownType.String); // // The GC requires a direct reference to frozen objects' EETypes. If System.String will be compiled into a separate // binary, it must be cloned into this one. // if (factory.CompilationModuleGroup.ShouldReferenceThroughImportTable(systemStringType)) { dataBuilder.EmitPointerReloc(factory.ConstructedClonedTypeSymbol(systemStringType)); } else { dataBuilder.EmitPointerReloc(factory.ConstructedTypeSymbol(systemStringType)); } dataBuilder.EmitInt(_data.Length); foreach (char c in _data) { dataBuilder.EmitShort((short)c); } // Null-terminate for friendliness with interop dataBuilder.EmitShort(0); }
private static IEnumerable<ICompilationRootProvider> GetCompilationRoots(IEnumerable<ICompilationRootProvider> existingRoots, NodeFactory factory) { yield return new CppCodegenCompilationRootProvider(factory.TypeSystemContext); foreach (var existingRoot in existingRoots) yield return existingRoot; }
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) { return new DependencyList { new DependencyListEntry(GetDictionaryLayout(factory), "Dictionary layout"), }; }
void EmitDispatchMap(ref ObjectDataBuilder builder, NodeFactory factory) { var entryCountReservation = builder.ReserveInt(); int entryCount = 0; for (int interfaceIndex = 0; interfaceIndex < _type.RuntimeInterfaces.Length; interfaceIndex++) { var interfaceType = _type.RuntimeInterfaces[interfaceIndex]; Debug.Assert(interfaceType.IsInterface); IReadOnlyList<MethodDesc> virtualSlots = factory.VTable(interfaceType).Slots; for (int interfaceMethodSlot = 0; interfaceMethodSlot < virtualSlots.Count; interfaceMethodSlot++) { MethodDesc declMethod = virtualSlots[interfaceMethodSlot]; var implMethod = _type.GetClosestDefType().ResolveInterfaceMethodToVirtualMethodOnType(declMethod); // Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface // dispatch will walk the inheritance chain). if (implMethod != null) { builder.EmitShort(checked((short)interfaceIndex)); builder.EmitShort(checked((short)interfaceMethodSlot)); builder.EmitShort(checked((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, implMethod))); entryCount++; } } } builder.EmitInt(entryCountReservation, entryCount); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); // The interface dispatch cell has an alignment requirement of 2 * [Pointer size] as part of the // synchronization mechanism of the two values in the runtime. objData.Alignment = _targetMethod.Context.Target.PointerSize * 2; objData.DefinedSymbols.Add(this); objData.EmitPointerReloc(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch")); // The second cell field uses the two lower-order bits to communicate the contents. // We add 1 to signal IDC_CachePointerIsInterfacePointer. See src\Native\Runtime\inc\rhbinder.h. objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_targetMethod.OwningType), 1); // End the run of dispatch cells objData.EmitZeroPointer(); // Avoid consulting VTable slots until they're guaranteed complete during final data emission if (!relocsOnly) { int interfaceMethodSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _targetMethod); if (factory.Target.PointerSize == 8) { objData.EmitLong(interfaceMethodSlot); } else { throw new NotImplementedException(); } } return objData.ToObjectData(); }
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) { DependencyList dependencies = null; TypeDesc owningType = _method.OwningType; if (factory.TypeSystemContext.HasEagerStaticConstructor(owningType)) { if (dependencies == null) dependencies = new DependencyList(); dependencies.Add(factory.EagerCctorIndirection(owningType.GetStaticConstructor()), "Eager .cctor"); } if (_ehInfo != null && _ehInfo.Relocs != null) { if (dependencies == null) dependencies = new DependencyList(); foreach (Relocation reloc in _ehInfo.Relocs) { dependencies.Add(reloc.Target, "reloc"); } } return dependencies; }
public ObjectDataBuilder(NodeFactory factory) { _target = factory.Target; _data = new ArrayBuilder<byte>(); _relocs = new ArrayBuilder<Relocation>(); Alignment = 1; DefinedSymbols = new ArrayBuilder<ISymbolNode>(); }
public override void EncodeData(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly) { builder.RequirePointerAlignment(); // At runtime, an instance of the GCStaticEEType will be created and a GCHandle to it // will be written in this location. builder.EmitPointerReloc(GetGCStaticEETypeNode(factory)); }
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) { // If there is a constructed version of this node in the graph, emit that instead if (ConstructedEETypeNode.CreationAllowed(_type)) return ((DependencyNode)factory.ConstructedTypeSymbol(_type)).Marked; return false; }
public ReadyToRunGenericHelperNode(NodeFactory factory, ReadyToRunHelperId helperId, object target, TypeSystemEntity dictionaryOwner) { _id = helperId; _dictionaryOwner = dictionaryOwner; _target = target; _lookupSignature = GetLookupSignature(factory, helperId, target); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.DefinedSymbols.Add(this); objData.RequirePointerAlignment(); objData.EmitZeroPointer(); return objData.ToObjectData(); }
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) { DefType closestDefType = _type.GetClosestDefType(); DependencyList dependencyList = new DependencyList(); if (_type.RuntimeInterfaces.Length > 0) { dependencyList.Add(factory.InterfaceDispatchMap(_type), "Interface dispatch map"); // If any of the implemented interfaces have variance, calls against compatible interface methods // could result in interface methods of this type being used (e.g. IEnumberable<object>.GetEnumerator() // can dispatch to an implementation of IEnumerable<string>.GetEnumerator()). // For now, we will not try to optimize this and we will pretend all interface methods are necessary. foreach (var implementedInterface in _type.RuntimeInterfaces) { if (implementedInterface.HasVariance) { foreach (var interfaceMethod in implementedInterface.GetAllMethods()) { if (interfaceMethod.Signature.IsStatic) continue; MethodDesc implMethod = closestDefType.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod); if (implMethod != null) { dependencyList.Add(factory.VirtualMethodUse(interfaceMethod), "Variant interface method"); dependencyList.Add(factory.VirtualMethodUse(implMethod), "Variant interface method"); } } } } } if (_type.IsArray) { // Array EEType depends on System.Array's virtuals. Array EETypes don't point to // their base type (i.e. there's no reloc based dependency making this "just work"). dependencyList.Add(factory.ConstructedTypeSymbol(_type.BaseType), "Array base type"); } dependencyList.Add(factory.VTable(_type), "VTable"); if (closestDefType.HasGenericDictionarySlot()) { // Generic dictionary pointer is part of the vtable and as such it gets only laid out // at the final data emission phase. We need to report it as a non-relocation dependency. dependencyList.Add(factory.TypeGenericDictionary(closestDefType), "Type generic dictionary"); } // Include the optional fields by default. We don't know if optional fields will be needed until // all of the interface usage has been stabilized. If we end up not needing it, the EEType node will not // generate any relocs to it, and the optional fields node will instruct the object writer to skip // emitting it. dependencyList.Add(_optionalFieldsNode, "Optional fields"); return dependencyList; }
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) { // Ensure that no duplicate EETypeOptionalFieldsNodes are emitted by letting the node Factory // pick a winner for each given EETypeOptionalFieldsBuilder if (factory.EETypeOptionalFields(_fieldBuilder) != this) return true; return !_fieldBuilder.IsAtLeastOneFieldUsed(); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { dataBuilder.RequirePointerAlignment(); StringDataNode stringDataNode = factory.StringData(_data); if (!relocsOnly) stringDataNode.SetId(base.Offset); dataBuilder.EmitPointerReloc(stringDataNode); }
protected override string GetName(NodeFactory factory) => $"Region {StartSymbol.GetMangledName(factory.NameMangler)}";
internal byte[] GetOptionalFieldsData(NodeFactory factory) { return(_optionalFieldsBuilder.GetBytes()); }
public static void GetTemplateTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) { if (!factory.MetadataManager.SupportsReflection) { return; } TypeDesc templateType = ConvertArrayOfTToRegularArray(factory, type); if (!IsEligibleToHaveATemplate(templateType)) { return; } if ((factory.Target.Abi == TargetAbi.ProjectN) && !ProjectNDependencyBehavior.EnableFullAnalysis) { // If the type does not have fully constructed type, don't track its dependencies. // TODO: Remove the workaround once we stop using the STS dependency analysis. IDependencyNode node = factory.MaximallyConstructableType(templateType); if (!node.Marked) { return; } } dependencies = dependencies ?? new DependencyList(); dependencies.Add(new DependencyListEntry(factory.NecessaryTypeSymbol(templateType), "Template type")); dependencies.Add(new DependencyListEntry(factory.NativeLayout.TemplateTypeLayout(templateType), "Template Type Layout")); }
public ImportedEETypeSymbolNode(NodeFactory factory, TypeDesc type) : base("__imp_" + factory.NameMangler.NodeMangler.EEType(type)) { _type = type; }
protected override void OnMarked(NodeFactory context) { //Debug.Assert(_type.IsTypeDefinition || !_type.HasSameTypeDefinition(context.ArrayOfTClass), "Asking for Array<T> EEType"); }
public static void AddDependenciesDueToMethodCodePresence(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { AddDependenciesDueToReflectability(ref dependencies, factory, method); if (method.HasInstantiation) { ExactMethodInstantiationsNode.GetExactMethodInstantiationDependenciesForMethod(ref dependencies, factory, method); if (method.IsVirtual) { // Generic virtual methods dependency tracking dependencies = dependencies ?? new DependencyList(); dependencies.Add(new DependencyListEntry(factory.GVMDependencies(method), "GVM Dependencies Support")); } GenericMethodsTemplateMap.GetTemplateMethodDependencies(ref dependencies, factory, method); } else { TypeDesc owningTemplateType = method.OwningType; // Unboxing and Instantiating stubs use a different type as their template if (factory.TypeSystemContext.IsSpecialUnboxingThunk(method)) { owningTemplateType = factory.TypeSystemContext.GetTargetOfSpecialUnboxingThunk(method).OwningType; } GenericTypesTemplateMap.GetTemplateTypeDependencies(ref dependencies, factory, owningTemplateType); } // On Project N, the compiler doesn't generate the interop code on the fly if (method.Context.Target.Abi != TargetAbi.ProjectN) { if (method.IsPInvoke) { if (dependencies == null) { dependencies = new DependencyList(); } MethodSignature methodSig = method.Signature; AddPInvokeParameterDependencies(ref dependencies, factory, methodSig.ReturnType); for (int i = 0; i < methodSig.Length; i++) { AddPInvokeParameterDependencies(ref dependencies, factory, methodSig[i]); } } } }
private static void AddPInvokeParameterDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc parameter) { if (parameter.IsDelegate) { dependencies.Add(factory.NecessaryTypeSymbol(parameter), "Delegate Marshalling Stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetOpenStaticDelegateMarshallingStub(parameter)), "Delegate Marshalling Stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetClosedDelegateMarshallingStub(parameter)), "Delegate Marshalling Stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetForwardDelegateCreationStub(parameter)), "Delegate Marshalling Stub"); } else if (Internal.TypeSystem.Interop.MarshalHelpers.IsStructMarshallingRequired(parameter)) { var stub = (Internal.IL.Stubs.StructMarshallingThunk)factory.InteropStubManager.GetStructMarshallingManagedToNativeStub(parameter); dependencies.Add(factory.ConstructedTypeSymbol(factory.InteropStubManager.GetStructMarshallingType(parameter)), "Struct Marshalling Type"); dependencies.Add(factory.MethodEntrypoint(stub), "Struct Marshalling stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingNativeToManagedStub(parameter)), "Struct Marshalling stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingCleanupStub(parameter)), "Struct Marshalling stub"); foreach (var inlineArrayCandidate in stub.GetInlineArrayCandidates()) { dependencies.Add(factory.ConstructedTypeSymbol(factory.InteropStubManager.GetInlineArrayType(inlineArrayCandidate)), "Struct Marshalling Type"); foreach (var method in inlineArrayCandidate.ElementType.GetMethods()) { dependencies.Add(factory.MethodEntrypoint(method), "inline array marshalling stub"); } } } }
public override DictionaryLayoutNode GetDictionaryLayout(NodeFactory factory) { return(factory.GenericDictionaryLayout(_owningType.ConvertToCanonForm(CanonicalFormKind.Specific))); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Build the GVM table entries from the list of interesting GVMTableEntryNodes foreach (var interestingEntry in factory.MetadataManager.GetTypeGVMEntries()) { foreach (var typeGVMEntryInfo in interestingEntry.ScanForGenericVirtualMethodEntries()) { AddGenericVirtualMethodImplementation(factory, typeGVMEntryInfo.CallingMethod, typeGVMEntryInfo.ImplementationMethod); } } // Ensure the native layout blob has been saved factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); NativeWriter nativeFormatWriter = new NativeWriter(); VertexHashtable gvmHashtable = new VertexHashtable(); Section gvmHashtableSection = nativeFormatWriter.NewSection(); gvmHashtableSection.Place(gvmHashtable); // Emit the GVM target information entries foreach (var gvmEntry in _gvmImplemenations) { Debug.Assert(!gvmEntry.Key.OwningType.IsInterface); foreach (var implementationEntry in gvmEntry.Value) { MethodDesc callingMethod = gvmEntry.Key; TypeDesc implementationType = implementationEntry.Key; MethodDesc implementationMethod = implementationEntry.Value; uint callingTypeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(callingMethod.OwningType)); Vertex vertex = nativeFormatWriter.GetUnsignedConstant(callingTypeId); uint targetTypeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationType)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant(targetTypeId)); var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(callingMethod)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(implementationMethod)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); int hashCode = callingMethod.OwningType.GetHashCode(); hashCode = ((hashCode << 13) ^ hashCode) ^ implementationType.GetHashCode(); gvmHashtable.Append((uint)hashCode, gvmHashtableSection.Place(vertex)); } } // Zero out the dictionary so that we AV if someone tries to insert after we're done. _gvmImplemenations = null; byte[] streamBytes = nativeFormatWriter.Save(); _endSymbol.SetSymbolOffset(streamBytes.Length); return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
public override IEnumerable <CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) { CombinedDependencyList list = null; factory.MetadataManager.GetConditionalDependenciesDueToMethodGenericDictionary(ref list, factory, _owningMethod); return(list ?? (IEnumerable <CombinedDependencyListEntry>)System.Array.Empty <CombinedDependencyListEntry>()); }
public override IEnumerable <CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) { // The generic dictionary layout is shared between all the canonically equivalent // instantiations. We need to track the dependencies of all canonical method bodies // that use the same dictionary layout. foreach (var method in _owningType.GetAllMethods()) { if (!EETypeNode.MethodHasNonGenericILMethodBody(method)) { continue; } // If a canonical method body was compiled, we need to track the dictionary // dependencies in the context of the concrete type that owns this dictionary. yield return(new CombinedDependencyListEntry( factory.ShadowConcreteMethod(method), factory.MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific)), "Generic dictionary dependency")); } }
public override DictionaryLayoutNode GetDictionaryLayout(NodeFactory factory) { return(factory.GenericDictionaryLayout(_owningMethod.GetCanonMethodTarget(CanonicalFormKind.Specific))); }
public abstract DictionaryLayoutNode GetDictionaryLayout(NodeFactory factory);
public GenericDictionaryNode(NodeFactory factory) { _factory = factory; }
protected override void EmitCode(NodeFactory factory, ref X86Emitter encoder, bool relocsOnly) { switch (Id) { case ReadyToRunHelperId.VirtualCall: { encoder.EmitINT3(); } break; case ReadyToRunHelperId.GetNonGCStaticBase: { MetadataType target = (MetadataType)Target; bool hasLazyStaticConstructor = factory.PreinitializationManager.HasLazyStaticConstructor(target); encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); if (!hasLazyStaticConstructor) { encoder.EmitRET(); } else { // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target), -NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target)); AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, factory.Target.PointerSize, 0, AddrModeSize.Int32); encoder.EmitCMP(ref initialized, 1); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } } break; case ReadyToRunHelperId.GetThreadStaticBase: { encoder.EmitINT3(); } break; case ReadyToRunHelperId.GetGCStaticBase: { encoder.EmitINT3(); } break; case ReadyToRunHelperId.DelegateCtor: { encoder.EmitINT3(); } break; case ReadyToRunHelperId.ResolveVirtualFunction: { encoder.EmitINT3(); } break; default: throw new NotImplementedException(); } }
/// <summary> /// Helper method to compute the dependencies that would be needed by a hashtable entry for a GVM call. /// This helper is used by the TypeGVMEntriesNode, which is used by the dependency analysis to compute the /// GVM hashtable entries for the compiled types. /// The dependencies returned from this function will be reported as static dependencies of the TypeGVMEntriesNode, /// which we create for each type that has generic virtual methods. /// </summary> public static DependencyList GetGenericVirtualMethodImplementationDependencies(NodeFactory factory, MethodDesc callingMethod, MethodDesc implementationMethod) { Debug.Assert(!callingMethod.OwningType.IsInterface); DependencyList dependencyNodes = new DependencyList(); // Compute the open method signatures MethodDesc openCallingMethod = callingMethod.GetTypicalMethodDefinition(); MethodDesc openImplementationMethod = implementationMethod.GetTypicalMethodDefinition(); var openCallingMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openCallingMethod); var openImplementationMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openImplementationMethod); dependencyNodes.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openCallingMethodNameAndSig), "gvm table calling method signature")); dependencyNodes.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openImplementationMethodNameAndSig), "gvm table implementation method signature")); return(dependencyNodes); }
/// <summary> /// Helper method to compute the dependencies that would be needed by a hashtable entry for a GVM call. /// This helper is used by the TypeGVMEntriesNode, which is used by the dependency analysis to compute the /// GVM hashtable entries for the compiled types. /// The dependencies returned from this function will be reported as static dependencies of the TypeGVMEntriesNode, /// which we create for each type that has generic virtual methods. /// </summary> public static void GetGenericVirtualMethodImplementationDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc callingMethod, MethodDesc implementationMethod) { Debug.Assert(!callingMethod.OwningType.IsInterface); if (!factory.MetadataManager.SupportsReflection) { return; } // Compute the open method signatures MethodDesc openCallingMethod = callingMethod.GetTypicalMethodDefinition(); MethodDesc openImplementationMethod = implementationMethod.GetTypicalMethodDefinition(); var openCallingMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openCallingMethod); var openImplementationMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openImplementationMethod); dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openCallingMethodNameAndSig), "gvm table calling method signature")); dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openImplementationMethodNameAndSig), "gvm table implementation method signature")); }
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
public static void AddDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { // TODO: https://github.com/dotnet/corert/issues/3224 // Reflection invoke stub handling is here because in the current reflection model we reflection-enable // all methods that are compiled. Ideally the list of reflection enabled methods should be known before // we even start the compilation process (with the invocation stubs being compilation roots like any other). // The existing model has it's problems: e.g. the invocability of the method depends on inliner decisions. if (factory.MetadataManager.IsReflectionInvokable(method)) { if (dependencies == null) { dependencies = new DependencyList(); } if (factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(method) && !method.IsCanonicalMethod(CanonicalFormKind.Any) /* Shared generics handled in the shadow concrete method node */) { MethodDesc canonInvokeStub = factory.MetadataManager.GetCanonicalReflectionInvokeStub(method); if (canonInvokeStub.IsSharedByGenericInstantiations) { dependencies.Add(new DependencyListEntry(factory.MetadataManager.DynamicInvokeTemplateData, "Reflection invoke template data")); factory.MetadataManager.DynamicInvokeTemplateData.AddDependenciesDueToInvokeTemplatePresence(ref dependencies, factory, canonInvokeStub); } else { dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(canonInvokeStub), "Reflection invoke")); } } bool skipUnboxingStubDependency = false; if (factory.Target.Abi == TargetAbi.ProjectN) { // ProjectN compilation currently computes the presence of these stubs independent from dependency analysis here // TODO: fix that issue and remove this odd treatment of unboxing stubs if (!method.HasInstantiation && method.OwningType.IsValueType && method.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any) && !method.Signature.IsStatic) { skipUnboxingStubDependency = true; } } if (method.OwningType.IsValueType && !method.Signature.IsStatic && !skipUnboxingStubDependency) { dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(method, unboxingStub: true), "Reflection unboxing stub")); } // If the method is defined in a different module than this one, a metadata token isn't known for performing the reference // Use a name/sig reference instead. if (!factory.MetadataManager.WillUseMetadataTokenToReferenceMethod(method)) { dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())), "Non metadata-local method reference")); } if (method.HasInstantiation && method.IsCanonicalMethod(CanonicalFormKind.Universal)) { dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method)), "UniversalCanon signature of method")); } ReflectionVirtualInvokeMapNode.GetVirtualInvokeMapDependencies(ref dependencies, factory, method); } }
/// <summary> /// Helper method to compute the dependencies that would be needed by a hashtable entry for an interface GVM call. /// This helper is used by the TypeGVMEntriesNode, which is used by the dependency analysis to compute the /// GVM hashtable entries for the compiled types. /// The dependencies returned from this function will be reported as static dependencies of the TypeGVMEntriesNode, /// which we create for each type that has generic virtual methods. /// </summary> public static void GetGenericVirtualMethodImplementationDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc callingMethod, TypeDesc implementationType, MethodDesc implementationMethod) { Debug.Assert(callingMethod.OwningType.IsInterface); if (!factory.MetadataManager.SupportsReflection) { return; } // Compute the open method signatures MethodDesc openCallingMethod = callingMethod.GetTypicalMethodDefinition(); MethodDesc openImplementationMethod = implementationMethod.GetTypicalMethodDefinition(); TypeDesc openImplementationType = implementationType.GetTypeDefinition(); var openCallingMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openCallingMethod); var openImplementationMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openImplementationMethod); dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openCallingMethodNameAndSig), "interface gvm table calling method signature")); dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openImplementationMethodNameAndSig), "interface gvm table implementation method signature")); if (!openImplementationType.IsInterface) { for (int index = 0; index < implementationType.RuntimeInterfaces.Length; index++) { if (implementationType.RuntimeInterfaces[index] == callingMethod.OwningType) { TypeDesc currentInterface = openImplementationType.RuntimeInterfaces[index]; var currentInterfaceSignature = factory.NativeLayout.TypeSignatureVertex(currentInterface); dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(currentInterfaceSignature), "interface gvm table interface signature")); } } } }
protected sealed override void EmitCode(NodeFactory factory, ref X86Emitter encoder, bool relocsOnly) { encoder.EmitINT3(); }
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => !factory.MetadataManager.SupportsReflection;
/// <summary> /// Validates that it will be possible to create an EEType for '<paramref name="type"/>'. /// </summary> public static void CheckCanGenerateEEType(NodeFactory factory, TypeDesc type) { // Don't validate generic definitons if (type.IsGenericDefinition) { return; } // System.__Canon or System.__UniversalCanon if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any)) { return; } // It must be possible to create an EEType for the base type of this type TypeDesc baseType = type.BaseType; if (baseType != null) { // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(GetFullCanonicalTypeForCanonicalType(baseType)); } // We need EETypes for interfaces foreach (var intf in type.RuntimeInterfaces) { // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(GetFullCanonicalTypeForCanonicalType(intf)); } // Validate classes, structs, enums, interfaces, and delegates DefType defType = type as DefType; if (defType != null) { // Ensure we can compute the type layout defType.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields); // // The fact that we generated an EEType means that someone can call RuntimeHelpers.RunClassConstructor. // We need to make sure this is possible. // if (factory.TypeSystemContext.HasLazyStaticConstructor(defType)) { defType.ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizesAndFields); } // Make sure instantiation length matches the expectation // TODO: it might be more resonable for the type system to enforce this (also for methods) if (defType.Instantiation.Length != defType.GetTypeDefinition().Instantiation.Length) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } foreach (TypeDesc typeArg in defType.Instantiation) { // ByRefs, pointers, function pointers, and System.Void are never valid instantiation arguments if (typeArg.IsByRef || typeArg.IsPointer || typeArg.IsFunctionPointer || typeArg.IsVoid) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } // TODO: validate constraints } // Check the type doesn't have bogus MethodImpls or overrides and we can get the finalizer. defType.GetFinalizer(); } // Validate parameterized types ParameterizedType parameterizedType = type as ParameterizedType; if (parameterizedType != null) { TypeDesc parameterType = parameterizedType.ParameterType; // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(parameterType); if (parameterizedType.IsArray) { if (parameterType.IsPointer || parameterType.IsFunctionPointer) { // Arrays of pointers and function pointers are not currently supported throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } int elementSize = parameterType.GetElementSize().AsInt; if (elementSize >= ushort.MaxValue) { // Element size over 64k can't be encoded in the GCDesc throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadValueClassTooLarge, parameterType); } if (((ArrayType)parameterizedType).Rank > 32) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadRankTooLarge, type); } } // Validate we're not constructing a type over a ByRef if (parameterType.IsByRef) { // CLR compat note: "ldtoken int32&&" will actually fail with a message about int32&; "ldtoken int32&[]" // will fail with a message about being unable to create an array of int32&. This is a middle ground. throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } // It might seem reasonable to disallow array of void, but the CLR doesn't prevent that too hard. // E.g. "newarr void" will fail, but "newarr void[]" or "ldtoken void[]" will succeed. } // Function pointer EETypes are not currently supported if (type.IsFunctionPointer) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Build the GVM table entries from the list of interesting GVMTableEntryNodes foreach (var interestingEntry in factory.MetadataManager.GetTypeGVMEntries()) { foreach (var typeGVMEntryInfo in interestingEntry.ScanForInterfaceGenericVirtualMethodEntries()) { AddGenericVirtualMethodImplementation(factory, typeGVMEntryInfo.CallingMethod, typeGVMEntryInfo.ImplementationType, typeGVMEntryInfo.ImplementationMethod); } } // Ensure the native layout blob has been saved factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); NativeWriter nativeFormatWriter = new NativeWriter(); VertexHashtable gvmHashtable = new VertexHashtable(); Section gvmHashtableSection = nativeFormatWriter.NewSection(); gvmHashtableSection.Place(gvmHashtable); // Emit the interface slot resolution entries foreach (var gvmEntry in _interfaceGvmSlots) { Debug.Assert(gvmEntry.Key.OwningType.IsInterface); MethodDesc callingMethod = gvmEntry.Key; // Emit the method signature and containing type of the current interface method uint typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(callingMethod.OwningType)); var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(callingMethod)); Vertex vertex = nativeFormatWriter.GetTuple( nativeFormatWriter.GetUnsignedConstant(typeId), nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); // Emit the method name / sig and containing type of each GVM target method for the current interface method entry vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)gvmEntry.Value.Count)); foreach (MethodDesc implementationMethod in gvmEntry.Value) { nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(implementationMethod)); typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationMethod.OwningType)); vertex = nativeFormatWriter.GetTuple( vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset), nativeFormatWriter.GetUnsignedConstant(typeId)); // Emit the interface GVM slot details for each type that implements the interface methods { Debug.Assert(_interfaceImpls.ContainsKey(implementationMethod)); var ifaceImpls = _interfaceImpls[implementationMethod]; // First, emit how many types have method implementations for this interface method entry vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)ifaceImpls.Count)); // Emit each type that implements the interface method, and the interface signatures for the interfaces implemented by the type foreach (var currentImpl in ifaceImpls) { TypeDesc implementationType = currentImpl.Key; typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationType)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant(typeId)); // Emit information on which interfaces the current method entry provides implementations for vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)currentImpl.Value.Count)); foreach (var ifaceId in currentImpl.Value) { // Emit the signature of the current interface implemented by the method Debug.Assert(((uint)ifaceId) < implementationType.RuntimeInterfaces.Length); TypeDesc currentInterface = implementationType.RuntimeInterfaces[ifaceId]; var typeSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.TypeSignatureVertex(currentInterface)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)typeSig.SavedVertex.VertexOffset)); } } } } int hashCode = callingMethod.OwningType.GetHashCode(); gvmHashtable.Append((uint)hashCode, gvmHashtableSection.Place(vertex)); } // Zero out the dictionary so that we AV if someone tries to insert after we're done. _interfaceGvmSlots = null; byte[] streamBytes = nativeFormatWriter.Save(); _endSymbol.SetSymbolOffset(streamBytes.Length); return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
protected virtual ISymbolNode GetBaseTypeNode(NodeFactory factory) { return(_type.BaseType != null?factory.NecessaryTypeSymbol(_type.BaseType) : null); }
public virtual ExportForm GetExportForm(NodeFactory factory) => ExportForm.ByName;
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // Dependencies for this node are tracked by the method code nodes if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Ensure the native layout data has been saved, in order to get valid Vertex offsets for the signature Vertices factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); NativeWriter nativeWriter = new NativeWriter(); VertexHashtable hashtable = new VertexHashtable(); Section nativeSection = nativeWriter.NewSection(); nativeSection.Place(hashtable); foreach (TypeDesc type in factory.MetadataManager.GetTypesWithConstructedEETypes()) { if (!IsEligibleToHaveATemplate(type)) { continue; } if ((factory.Target.Abi == TargetAbi.ProjectN) && !ProjectNDependencyBehavior.EnableFullAnalysis) { // If the type does not have fully constructed type, don't track its dependencies. // TODO: Remove the workaround once we stop using the STS dependency analysis. IDependencyNode node = factory.MaximallyConstructableType(type); if (!node.Marked) { continue; } } // Type's native layout info NativeLayoutTemplateTypeLayoutVertexNode templateNode = factory.NativeLayout.TemplateTypeLayout(type); // If this template isn't considered necessary, don't emit it. if (!templateNode.Marked) { continue; } Vertex nativeLayout = templateNode.SavedVertex; // Hashtable Entry Vertex entry = nativeWriter.GetTuple( nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(type))), nativeWriter.GetUnsignedConstant((uint)nativeLayout.VertexOffset)); // Add to the hash table, hashed by the containing type's hashcode uint hashCode = (uint)type.GetHashCode(); hashtable.Append(hashCode, nativeSection.Place(entry)); } byte[] streamBytes = nativeWriter.Save(); _endSymbol.SetSymbolOffset(streamBytes.Length); return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }
public MrtProcessedExportAddressTableNode(string symbolName, NodeFactory factory) { _symbolName = symbolName; _factory = factory; }
protected sealed override string GetName(NodeFactory factory) { return(this.GetMangledName(factory.NameMangler)); }
protected virtual void EmitDataInternal(ref ObjectDataBuilder builder, NodeFactory factory, bool fixedLayoutOnly) { DictionaryLayoutNode layout = GetDictionaryLayout(factory); layout.EmitDictionaryData(ref builder, factory, this, fixedLayoutOnly: fixedLayoutOnly); }