|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Internal.Text;
using Internal.TypeSystem;
using Debug = System.Diagnostics.Debug;
namespace ILCompiler.DependencyAnalysis
{
/// <summary>
/// Contains all GC static fields for a particular MethodTable.
/// Fields that have preinitialized data are pointer reloc pointing to frozen objects.
/// Other fields are initialized with 0.
/// We simply memcpy these over the GC static MethodTable object.
/// </summary>
public class GCStaticsPreInitDataNode : ObjectNode, ISymbolDefinitionNode
{
private TypePreinit.PreinitializationInfo _preinitializationInfo;
public GCStaticsPreInitDataNode(TypePreinit.PreinitializationInfo preinitializationInfo)
{
Debug.Assert(!preinitializationInfo.Type.IsCanonicalSubtype(CanonicalFormKind.Specific));
_preinitializationInfo = preinitializationInfo;
}
protected override string GetName(NodeFactory factory) => GetMangledName(_preinitializationInfo.Type, factory.NameMangler);
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(GetMangledName(_preinitializationInfo.Type, nameMangler));
}
public int Offset => 0;
public MetadataType Type => _preinitializationInfo.Type;
public static string GetMangledName(TypeDesc type, NameMangler nameMangler)
{
return nameMangler.NodeMangler.GCStatics(type) + "__PreInitData";
}
public override bool StaticDependenciesAreComputed => true;
public override ObjectNodeSection GetSection(NodeFactory factory)
{
if (factory.Target.IsWindows)
return ObjectNodeSection.ReadOnlyDataSection;
else
return ObjectNodeSection.DataSection;
}
public override bool IsShareable => EETypeNode.IsTypeNodeShareable(_preinitializationInfo.Type);
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
MetadataType type = _preinitializationInfo.Type;
builder.RequireInitialAlignment(factory.Target.PointerSize);
// GC static fields don't begin at offset 0, need to subtract that.
int initialOffset = CompilerMetadataFieldLayoutAlgorithm.GetGCStaticFieldOffset(factory.TypeSystemContext).AsInt;
foreach (FieldDesc field in type.GetFields())
{
if (!field.IsStatic || field.HasRva || field.IsLiteral || field.IsThreadStatic || !field.HasGCStaticBase)
continue;
int padding = field.Offset.AsInt - initialOffset - builder.CountBytes;
Debug.Assert(padding >= 0);
builder.EmitZeros(padding);
TypePreinit.ISerializableValue val = _preinitializationInfo.GetFieldValue(field);
int currentOffset = builder.CountBytes;
if (val != null)
val.WriteFieldData(ref builder, factory);
else
builder.EmitZeroPointer();
Debug.Assert(builder.CountBytes - currentOffset == field.FieldType.GetElementSize().AsInt);
}
int pad = _preinitializationInfo.Type.GCStaticFieldSize.AsInt - builder.CountBytes - initialOffset;
Debug.Assert(pad >= 0);
builder.EmitZeros(pad);
builder.AddSymbol(this);
return builder.ToObjectData();
}
public override int ClassCode => 1148300665;
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_preinitializationInfo.Type, ((GCStaticsPreInitDataNode)other)._preinitializationInfo.Type);
}
}
}
|