|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using Internal.Runtime;
using Internal.TypeSystem;
namespace ILCompiler.DependencyAnalysis
{
public sealed class ConstructedEETypeNode : EETypeNode
{
public ConstructedEETypeNode(NodeFactory factory, TypeDesc type) : base(factory, type)
{
Debug.Assert(!type.IsCanonicalDefinitionType(CanonicalFormKind.Any));
CheckCanGenerateConstructedEEType(factory, type);
}
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler) + " constructed";
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => false;
protected override bool EmitVirtualSlots => true;
protected override bool IsReflectionVisible => true;
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
DependencyList dependencyList = base.ComputeNonRelocationBasedDependencies(factory);
if (_type.IsIDynamicInterfaceCastable)
{
dependencyList.Add(factory.AnalysisCharacteristic("DynamicInterfaceCastablePresent"), "Implements IDynamicInterfaceCastable");
}
// Ensure that we track the metadata type symbol if we are working with a constructed type symbol.
// The emitter will ensure we don't emit both, but this allows us assert that we only generate
// relocs to nodes we emit.
dependencyList.Add(factory.MetadataTypeSymbol(_type), "MetadataType for constructed type");
DefType closestDefType = _type.GetClosestDefType();
if (_type.IsArray)
{
// Array MethodTable 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");
ArrayType arrayType = (ArrayType)_type;
if (arrayType.IsMdArray && arrayType.Rank == 1)
{
// Allocating an MDArray of Rank 1 with zero lower bounds results in allocating
// an SzArray instead. Make sure the type loader can find the SzArray type.
dependencyList.Add(factory.ConstructedTypeSymbol(arrayType.ElementType.MakeArrayType()), "Rank 1 array");
}
}
dependencyList.Add(factory.VTable(closestDefType), "VTable");
if (!_type.IsCanonicalSubtype(CanonicalFormKind.Any))
{
factory.InteropStubManager.AddInterestingInteropConstructedTypeDependencies(ref dependencyList, factory, _type);
}
return dependencyList;
}
protected override ISymbolNode GetBaseTypeNode(NodeFactory factory)
{
return _type.BaseType != null ? factory.ConstructedTypeSymbol(_type.BaseType.NormalizeInstantiation()) : null;
}
protected override FrozenRuntimeTypeNode GetFrozenRuntimeTypeNode(NodeFactory factory)
{
Debug.Assert(!_type.IsCanonicalSubtype(CanonicalFormKind.Any));
return factory.SerializedMetadataRuntimeTypeObject(_type);
}
protected override ISymbolNode GetNonNullableValueTypeArrayElementTypeNode(NodeFactory factory)
{
return factory.ConstructedTypeSymbol(((ArrayType)_type).ElementType);
}
protected override IEETypeNode GetInterfaceTypeNode(NodeFactory factory, TypeDesc interfaceType)
{
// The interface type will be visible to reflection and should be considered constructed.
return factory.ConstructedTypeSymbol(interfaceType.NormalizeInstantiation());
}
protected override int GCDescSize => GCDescEncoder.GetGCDescSize(_type);
protected override void OutputGCDesc(ref ObjectDataBuilder builder)
{
GCDescEncoder.EncodeGCDesc(ref builder, _type);
}
public static bool CreationAllowed(TypeDesc type)
{
switch (type.Category)
{
case TypeFlags.Pointer:
case TypeFlags.FunctionPointer:
case TypeFlags.ByRef:
// Pointers and byrefs are not boxable
return false;
case TypeFlags.Array:
case TypeFlags.SzArray:
// TODO: any validation for arrays?
break;
default:
// Generic definition EETypes can't be allocated
if (type.IsGenericDefinition)
return false;
// Full MethodTable of System.Canon should never be used.
if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any))
return false;
// The global "<Module>" type can never be allocated.
if (((MetadataType)type).IsModuleType)
return false;
break;
}
return true;
}
public static void CheckCanGenerateConstructedEEType(NodeFactory factory, TypeDesc type)
{
if (!CreationAllowed(type))
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
}
public override int ClassCode => 590142654;
}
}
|