Merge pull request #4354 from dotnet/nmirror

Merge nmirror to master
This commit is contained in:
Jan Kotas 2017-08-22 09:48:27 -07:00 коммит произвёл GitHub
Родитель 61b3a728cf 9703b44fea
Коммит 4135dc55b4
47 изменённых файлов: 2837 добавлений и 177 удалений

Просмотреть файл

@ -48,6 +48,15 @@ namespace System.Collections.Generic
_count += length;
}
public void Append(ArrayBuilder<T> newItems)
{
if (newItems.Count == 0)
return;
EnsureCapacity(_count + newItems.Count);
Array.Copy(newItems._items, 0, _items, _count, newItems.Count);
_count += newItems.Count;
}
public void ZeroExtend(int numItems)
{
Debug.Assert(numItems >= 0);

Просмотреть файл

@ -0,0 +1,778 @@
// 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.Diagnostics;
using Internal.Text;
using BlobBuilder = System.Reflection.Metadata.BlobBuilder;
using Blob = System.Reflection.Metadata.Blob;
namespace Internal.TypeSystem.TypesDebugInfo
{
class DebugInfoBlob
{
ArrayBuilder<byte> _data;
public byte[] ToArray() => _data.ToArray();
public uint Size() { return (uint)_data.Count; }
public uint DWORDAlignedSize(uint size)
{
checked
{
if ((size + Size()) % 4 != 0)
{
size = size + 4 - ((size + Size()) % 4);
}
}
return size;
}
public void AlignToDWORD()
{
if ((Size() % 4) != 0)
{
uint pad = 4 - (Size() % 4);
for (uint i = pad; i > 0; i--)
{
WriteBYTE((byte)(0xF0 | i)); // Insert LF_PADX entries.
}
}
}
public void SetWORDAtBlobIndex(uint blobIndex, ushort src)
{
_data[(int)blobIndex] = (byte)src;
_data[(int)blobIndex + 1] = (byte)(src >> 8);
}
public void SetDWORDAtBlobIndex(uint blobIndex, uint src)
{
_data[(int)blobIndex] = (byte)src;
_data[(int)blobIndex + 1] = (byte)(src >> 8);
_data[(int)blobIndex + 2] = (byte)(src >> 16);
_data[(int)blobIndex + 3] = (byte)(src >> 24);
}
public void WriteBYTE(byte src)
{
_data.Add(src);
}
public void WriteWORD(ushort src)
{
_data.Add((byte)src);
_data.Add((byte)(src >> 8));
}
public void WriteDWORD(uint src)
{
_data.Add((byte)src);
_data.Add((byte)(src >> 8));
_data.Add((byte)(src >> 16));
_data.Add((byte)(src >> 24));
}
public void WriteString(Utf8String utf8String)
{
_data.Append(utf8String.UnderlyingArray);
_data.Add(0);
}
public void WriteString(string str)
{
WriteString(new Utf8String(str));
}
public void WriteBuffer(byte[] data)
{
_data.Append(data);
}
public void WriteBuffer(DebugInfoBlob debugInfoBlob)
{
_data.Append(debugInfoBlob._data);
}
public void WriteBuffer(BlobBuilder blobBuilder)
{
foreach (Blob blob in blobBuilder.GetBlobs())
{
ArraySegment<byte> byteChunk = blob.GetBytes();
this.WriteBuffer(byteChunk.Array, byteChunk.Offset, byteChunk.Count);
}
}
public void WriteBuffer(byte[] data, int index, int length)
{
_data.Append(data, index, length);
}
public void WriteQWORD(ulong src)
{
_data.Add((byte)src);
_data.Add((byte)(src >> 8));
_data.Add((byte)(src >> 16));
_data.Add((byte)(src >> 24));
_data.Add((byte)(src >> 32));
_data.Add((byte)(src >> 40));
_data.Add((byte)(src >> 48));
_data.Add((byte)(src >> 56));
}
public static uint StringLengthEncoded(Utf8String str)
{
return checked((uint)str.Length + 1);
}
}
class DebugInfoWriter
{
enum LeafKind : ushort
{
// values used for type records
LF_VTSHAPE = 0x000a,
LF_POINTER = 0x1002,
LF_PROCEDURE = 0x1008,
LF_MFUNCTION = 0x1009,
LF_ARGLIST = 0x1201,
LF_FIELDLIST = 0x1203,
LF_BCLASS = 0x1400,
LF_INDEX = 0x1404,
LF_VFUNCTAB = 0x1409,
LF_ENUMERATE = 0x1502,
LF_ARRAY = 0x1503,
LF_CLASS = 0x1504,
LF_STRUCTURE = 0x1505,
LF_ENUM = 0x1507,
LF_MEMBER = 0x150d,
LF_STATICMEMBER = 0x150e,
LF_MFUNC_ID = 0x1602, // member func ID
// values used for numeric leafs
LF_CHAR = 0x8000,
LF_SHORT = 0x8001,
LF_LONG = 0x8003,
LF_ULONG = 0x8004,
LF_QUADWORD = 0x8009
};
enum LF_CLASS_Properties : ushort
{
None = 0x0000,
ForwardReference = 0x0080
}
enum CV_Visibility : ushort
{
Private = 0x1,
Protected = 0x2,
Public = 0x3
}
class TypeRecordsBlob : DebugInfoBlob
{
uint _currentTypeIndex = 0x1000;
public uint GetNextTypeIndex()
{
Debug.Assert((Size() % 4) == 0);
return _currentTypeIndex++;
}
public void WriteCV_Visibility(CV_Visibility src)
{
WriteWORD((ushort)src);
}
public void WriteLeafKind(LeafKind src)
{
WriteWORD((ushort)src);
}
public void WriteLF_CLASS_Properties(LF_CLASS_Properties src)
{
WriteWORD((ushort)src);
}
public void WriteNumericLeaf(ulong value)
{
long signedValue = (long)value;
if (signedValue < 0)
{
if (signedValue >= -0x80)
{
WriteLeafKind(LeafKind.LF_CHAR);
WriteBYTE((byte)value);
}
else if (signedValue >= -0x8000)
{
WriteLeafKind(LeafKind.LF_SHORT);
WriteWORD((ushort)value);
}
else if (signedValue >= -0x80000000)
{
WriteLeafKind(LeafKind.LF_LONG);
WriteDWORD((uint)value);
}
else
{
WriteLeafKind(LeafKind.LF_QUADWORD);
WriteQWORD(value);
}
}
else
{
if (value < 0x8000)
{
WriteWORD((ushort)value);
}
else if (value <= 0x7FFFFFFF)
{
WriteLeafKind(LeafKind.LF_LONG);
WriteDWORD((uint)value);
}
else if (value <= 0xFFFFFFFF)
{
WriteLeafKind(LeafKind.LF_ULONG);
WriteDWORD((uint)value);
}
else
{
WriteLeafKind(LeafKind.LF_QUADWORD);
WriteQWORD(value);
}
}
}
public void WriteNumericLeaf(long value)
{
if (value < 0)
{
if (value >= -0x80)
{
WriteLeafKind(LeafKind.LF_CHAR);
WriteBYTE((byte)value);
}
else if (value >= -0x8000)
{
WriteLeafKind(LeafKind.LF_SHORT);
WriteWORD((ushort)value);
}
else if (value >= -0x80000000)
{
WriteLeafKind(LeafKind.LF_LONG);
WriteDWORD((uint)value);
}
else
{
WriteLeafKind(LeafKind.LF_QUADWORD);
WriteQWORD((ulong)value);
}
}
else
{
if (value < 0x8000)
{
WriteWORD((ushort)value);
}
else if (value <= 0x7FFFFFFF)
{
WriteLeafKind(LeafKind.LF_LONG);
WriteDWORD((uint)value);
}
else if (value <= 0xFFFFFFFF)
{
WriteLeafKind(LeafKind.LF_ULONG);
WriteDWORD((uint)value);
}
else
{
WriteLeafKind(LeafKind.LF_QUADWORD);
WriteQWORD((ulong)value);
}
}
}
public static uint NumericLeafSize(long value)
{
if (value < 0)
{
if (value >= -0x80)
return 2 + 1;
else if (value >= -0x8000)
return 2 + 2;
else if (value >= -0x80000000L)
return 2 + 4;
else
return 2 + 8;
}
else
{
if (value < 0x8000)
return 2;
else if (value <= 0x7FFFFFFF || value <= 0xFFFFFFFF)
return 2 + 4;
else
return 2 + 8;
}
}
public static uint NumericLeafSize(ulong value)
{
long signedValue = (long)value;
if (signedValue < 0)
{
if (signedValue >= -0x80)
return 2 + 1;
else if (signedValue >= -0x8000)
return 2 + 2;
else if (signedValue >= -0x80000000L)
return 2 + 4;
else
return 2 + 8;
}
else
{
if (value < 0x8000)
return 2;
else if (value <= 0x7FFFFFFF || value <= 0xFFFFFFFF)
return 2 + 4;
else
return 2 + 8;
}
}
}
TypeRecordsBlob _blob = new TypeRecordsBlob();
uint _tiVTShapePointer;
public DebugInfoWriter()
{
// Write header
_blob.WriteBYTE(0x04);
_blob.WriteBYTE(0x00);
_blob.WriteBYTE(0x00);
_blob.WriteBYTE(0x00);
// Write out vtable shape pointer. Various other contents of this file will refer to it.
_tiVTShapePointer = EmitVFuncTableShapeDebugType();
}
private struct FieldListInProgress
{
public uint TypeIndexOfFieldList;
public uint BlobOffsetCurrentFieldListChunk;
public ushort FieldsCount;
}
public void VerifyBlobEligibleToBeBetweenRecords()
{
Debug.Assert((_blob.Size() % 4) == 0);
}
private FieldListInProgress StartFieldList()
{
Debug.Assert((_blob.Size() % 4) == 0);
FieldListInProgress fieldListInProgress = new FieldListInProgress();
fieldListInProgress.BlobOffsetCurrentFieldListChunk = _blob.Size();
fieldListInProgress.TypeIndexOfFieldList = _blob.GetNextTypeIndex();
fieldListInProgress.FieldsCount = 0;
_blob.WriteWORD(0);
_blob.WriteLeafKind(LeafKind.LF_FIELDLIST);
return fieldListInProgress;
}
private void FinalizeFieldList(FieldListInProgress fieldListInProgress)
{
ushort length = checked((ushort)(_blob.Size() - fieldListInProgress.BlobOffsetCurrentFieldListChunk - 2));
_blob.SetWORDAtBlobIndex(fieldListInProgress.BlobOffsetCurrentFieldListChunk, length);
}
private void ExtendFieldList(ref FieldListInProgress fieldListInProgress, uint newDataLength, out bool mustSkipEmission)
{
checked
{
if (fieldListInProgress.FieldsCount == 0xFFFF)
{
mustSkipEmission = true;
return;
}
mustSkipEmission = false;
fieldListInProgress.FieldsCount++;
if ((_blob.Size() + newDataLength + 11/* size of LF_INDEX + maximum possible padding*/ - fieldListInProgress.BlobOffsetCurrentFieldListChunk) > 0xFF00)
{
Debug.Assert((_blob.Size() % 4) == 0);
// Add LF_INDEX record to push forward
_blob.WriteLeafKind(LeafKind.LF_INDEX);
_blob.WriteWORD(0); // pad0
uint newFieldListTypeIndex = _blob.GetNextTypeIndex();
_blob.WriteDWORD(newFieldListTypeIndex);
FinalizeFieldList(fieldListInProgress);
Debug.Assert((_blob.Size() % 4) == 0);
fieldListInProgress.BlobOffsetCurrentFieldListChunk = _blob.Size();
_blob.WriteWORD(0);
_blob.WriteLeafKind(LeafKind.LF_FIELDLIST);
}
}
}
private void EmitBaseClass(ref FieldListInProgress fieldListInProgress, uint baseClassIndex)
{
Debug.Assert((_blob.Size() % 4) == 0);
bool mustSkipEmission;
ExtendFieldList(ref fieldListInProgress, 8 + TypeRecordsBlob.NumericLeafSize(0), out mustSkipEmission);
if (mustSkipEmission)
return;
_blob.WriteLeafKind(LeafKind.LF_BCLASS);
_blob.WriteCV_Visibility(CV_Visibility.Public);
_blob.WriteDWORD(baseClassIndex);
_blob.WriteNumericLeaf(0);
_blob.AlignToDWORD();
VerifyBlobEligibleToBeBetweenRecords();
}
private void EmitDataMember(ref FieldListInProgress fieldListInProgress, uint type, int offset, Utf8String name)
{
Debug.Assert((_blob.Size() % 4) == 0);
bool isStaticField = (uint)offset == 0xFFFFFFFF;
bool mustSkipEmission;
uint recordSize = 8 + (isStaticField ? 0 : TypeRecordsBlob.NumericLeafSize(offset)) + DebugInfoBlob.StringLengthEncoded(name);
ExtendFieldList(ref fieldListInProgress, recordSize, out mustSkipEmission);
if (mustSkipEmission)
return;
_blob.WriteLeafKind(isStaticField ? LeafKind.LF_STATICMEMBER : LeafKind.LF_MEMBER);
_blob.WriteCV_Visibility(CV_Visibility.Public);
_blob.WriteDWORD(type);
if (!isStaticField)
_blob.WriteNumericLeaf(offset);
_blob.WriteString(name);
_blob.AlignToDWORD();
VerifyBlobEligibleToBeBetweenRecords();
}
private void EmitEnumerate(ref FieldListInProgress fieldListInProgress, ulong value, Utf8String name)
{
Debug.Assert((_blob.Size() % 4) == 0);
bool mustSkipEmission;
uint recordSize = 4 + TypeRecordsBlob.NumericLeafSize(value) + DebugInfoBlob.StringLengthEncoded(name);
ExtendFieldList(ref fieldListInProgress, recordSize, out mustSkipEmission);
if (mustSkipEmission)
return;
_blob.WriteLeafKind(LeafKind.LF_ENUMERATE);
_blob.WriteCV_Visibility(CV_Visibility.Public);
_blob.WriteNumericLeaf(value);
_blob.WriteString(name);
_blob.AlignToDWORD();
VerifyBlobEligibleToBeBetweenRecords();
}
private uint EmitVFuncTableShapeDebugType()
{
Debug.Assert((_blob.Size() % 4) == 0);
uint vFuncTableShapeTypeIndex = _blob.GetNextTypeIndex();
uint recordSize = 10;
_blob.WriteWORD((ushort)(_blob.DWORDAlignedSize(recordSize) - 2));
_blob.WriteLeafKind(LeafKind.LF_VTSHAPE);
_blob.WriteWORD(0);
_blob.WriteDWORD(0);
_blob.AlignToDWORD();
VerifyBlobEligibleToBeBetweenRecords();
return vFuncTableShapeTypeIndex;
}
private void EmitVFuncTab(ref FieldListInProgress fieldListInProgress)
{
Debug.Assert((_blob.Size() % 4) == 0);
bool mustSkipEmission;
uint recordSize = 8;
ExtendFieldList(ref fieldListInProgress, recordSize, out mustSkipEmission);
if (mustSkipEmission)
return;
_blob.WriteLeafKind(LeafKind.LF_VFUNCTAB);
_blob.WriteWORD(0);
_blob.WriteDWORD(_tiVTShapePointer);
VerifyBlobEligibleToBeBetweenRecords();
}
public uint GetClassTypeIndex(ClassTypeDescriptor classTypeDescriptor)
{
FieldListInProgress fieldList = default(FieldListInProgress);
if (classTypeDescriptor.BaseClassId != 0)
{
fieldList = StartFieldList();
EmitBaseClass(ref fieldList, classTypeDescriptor.BaseClassId);
FinalizeFieldList(fieldList);
}
uint classTypeIndex = _blob.GetNextTypeIndex();
Utf8String name = new Utf8String(classTypeDescriptor.Name);
uint recordSize = 20 + DebugInfoBlob.StringLengthEncoded(name) + TypeRecordsBlob.NumericLeafSize(0) /*size of length */;
_blob.WriteWORD(checked((ushort)(_blob.DWORDAlignedSize(recordSize) - 2))); // don't include size of 'length' in 'length'
_blob.WriteLeafKind(classTypeDescriptor.IsStruct != 0 ? LeafKind.LF_STRUCTURE : LeafKind.LF_CLASS);
_blob.WriteWORD(fieldList.FieldsCount);
_blob.WriteLF_CLASS_Properties(LF_CLASS_Properties.ForwardReference);
_blob.WriteDWORD(fieldList.TypeIndexOfFieldList);
_blob.WriteDWORD(0); // Derivation list is not filled in here
_blob.WriteDWORD(0); // No vtable shape
_blob.WriteNumericLeaf(0);
_blob.WriteString(name);
_blob.AlignToDWORD();
VerifyBlobEligibleToBeBetweenRecords();
return classTypeIndex;
}
public uint GetCompleteClassTypeIndex(ClassTypeDescriptor classTypeDescriptor, ClassFieldsTypeDescriptor classFieldsTypeDescriptior, DataFieldDescriptor[] fields)
{
FieldListInProgress fieldList = default(FieldListInProgress);
if ((classTypeDescriptor.BaseClassId != 0) || (fields != null && fields.Length > 0) || (classTypeDescriptor.IsStruct == 0))
{
fieldList = StartFieldList();
if (classTypeDescriptor.BaseClassId != 0)
EmitBaseClass(ref fieldList, classTypeDescriptor.BaseClassId);
if (classTypeDescriptor.IsStruct == 0)
EmitVFuncTab(ref fieldList);
if (fields != null)
{
foreach (DataFieldDescriptor field in fields)
{
EmitDataMember(ref fieldList, field.FieldTypeIndex, (int)field.Offset, new Utf8String(field.Name));
}
}
FinalizeFieldList(fieldList);
}
uint classTypeIndex = _blob.GetNextTypeIndex();
Utf8String name = new Utf8String(classTypeDescriptor.Name);
uint recordSize = 20 + DebugInfoBlob.StringLengthEncoded(name) + TypeRecordsBlob.NumericLeafSize(classFieldsTypeDescriptior.Size) /*size of length */;
_blob.WriteWORD(checked((ushort)(_blob.DWORDAlignedSize(recordSize) - 2))); // don't include size of 'length' in 'length'
_blob.WriteLeafKind(classTypeDescriptor.IsStruct != 0 ? LeafKind.LF_STRUCTURE : LeafKind.LF_CLASS);
_blob.WriteWORD(fieldList.FieldsCount);
_blob.WriteLF_CLASS_Properties(LF_CLASS_Properties.None);
_blob.WriteDWORD(fieldList.TypeIndexOfFieldList);
_blob.WriteDWORD(0); // Derivation list is not filled in here
_blob.WriteDWORD(_tiVTShapePointer); // No vtable shape
_blob.WriteNumericLeaf(classFieldsTypeDescriptior.Size);
_blob.WriteString(name);
_blob.AlignToDWORD();
VerifyBlobEligibleToBeBetweenRecords();
return classTypeIndex;
}
public uint GetEnumTypeIndex(EnumTypeDescriptor enumTypeDescriptor, EnumRecordTypeDescriptor[] enumerates)
{
checked
{
FieldListInProgress fieldList = default(FieldListInProgress);
if ((enumerates != null && enumerates.Length > 0))
{
fieldList = StartFieldList();
foreach (EnumRecordTypeDescriptor enumerate in enumerates)
{
EmitEnumerate(ref fieldList, enumerate.Value, new Utf8String(enumerate.Name));
}
FinalizeFieldList(fieldList);
}
if (enumerates != null)
Debug.Assert(checked((int)enumTypeDescriptor.ElementCount == enumerates.Length));
if (enumerates == null)
Debug.Assert(enumTypeDescriptor.ElementCount == 0);
uint enumTypeIndex = _blob.GetNextTypeIndex();
Utf8String name = new Utf8String(enumTypeDescriptor.Name);
uint recordSize = 16 + DebugInfoBlob.StringLengthEncoded(name);
_blob.WriteWORD(checked((ushort)(_blob.DWORDAlignedSize(recordSize) - 2))); // don't include size of 'length' in 'length'
_blob.WriteLeafKind(LeafKind.LF_ENUM);
_blob.WriteWORD(fieldList.FieldsCount);
_blob.WriteWORD(0);
_blob.WriteDWORD((uint)enumTypeDescriptor.ElementType);
_blob.WriteDWORD(fieldList.TypeIndexOfFieldList);
_blob.WriteString(name);
_blob.AlignToDWORD();
VerifyBlobEligibleToBeBetweenRecords();
return enumTypeIndex;
}
}
public uint GetArgListTypeDescriptor(uint[] arguments)
{
uint argListTypeIndex = _blob.GetNextTypeIndex();
ushort recordSizeEmit;
uint argumentListEmit;
try
{
checked
{
uint recordSize = (ushort)(8 + (4 * arguments.Length));
recordSizeEmit = checked((ushort)(_blob.DWORDAlignedSize(recordSize) - 2));
argumentListEmit = (uint)arguments.Length;
}
}
catch (OverflowException)
{
return 0;
}
_blob.WriteWORD(recordSizeEmit); // don't include size of 'length' in 'length'
_blob.WriteLeafKind(LeafKind.LF_ARGLIST);
_blob.WriteDWORD(argumentListEmit);
foreach (uint argType in arguments)
{
_blob.WriteDWORD(argType);
}
VerifyBlobEligibleToBeBetweenRecords();
return argListTypeIndex;
}
public uint GetMemberFunctionTypeIndex(MemberFunctionTypeDescriptor memberDescriptor, uint[] arguments)
{
uint argumentList = GetArgListTypeDescriptor(arguments);
if (argumentList == 0)
return 0;
uint memberFunctionTypeIndex = _blob.GetNextTypeIndex();
uint recordSize = 28;
_blob.WriteWORD(checked((ushort)(_blob.DWORDAlignedSize(recordSize) - 2))); // don't include size of 'length' in 'length'
_blob.WriteLeafKind(LeafKind.LF_MFUNCTION);
_blob.WriteDWORD(memberDescriptor.ReturnType);
_blob.WriteDWORD(memberDescriptor.ContainingClass);
_blob.WriteDWORD(memberDescriptor.TypeIndexOfThisPointer);
_blob.WriteBYTE(checked((byte)memberDescriptor.CallingConvention));
_blob.WriteBYTE(0);
_blob.WriteWORD(checked((ushort)arguments.Length));
_blob.WriteDWORD(argumentList);
_blob.WriteDWORD(memberDescriptor.ThisAdjust);
VerifyBlobEligibleToBeBetweenRecords();
return memberFunctionTypeIndex;
}
public uint GetMemberFunctionId(MemberFunctionIdTypeDescriptor memberIdDescriptor)
{
uint memberFunctionIdTypeIndex = _blob.GetNextTypeIndex();
Utf8String name = new Utf8String(memberIdDescriptor.Name);
uint recordSize = 12 + DebugInfoBlob.StringLengthEncoded(name);
_blob.WriteWORD(checked((ushort)(_blob.DWORDAlignedSize(recordSize) - 2))); // don't include size of 'length' in 'length'
_blob.WriteLeafKind(LeafKind.LF_MFUNC_ID);
_blob.WriteDWORD(memberIdDescriptor.MemberFunction);
_blob.WriteDWORD(memberIdDescriptor.ParentClass);
_blob.WriteString(name);
_blob.AlignToDWORD();
VerifyBlobEligibleToBeBetweenRecords();
return memberFunctionIdTypeIndex;
}
public uint GetPointerTypeIndex(PointerTypeDescriptor pointerTypeDescriptor)
{
uint pointerTypeIndex = _blob.GetNextTypeIndex();
uint recordSize = 12;
uint attr = 0;
if (pointerTypeDescriptor.IsReference != 0)
attr |= 0x20;
if (pointerTypeDescriptor.IsConst != 0)
attr |= 0x400;
if (pointerTypeDescriptor.Is64Bit != 0)
attr |= 12;
else
attr |= 10;
_blob.WriteWORD(checked((ushort)(_blob.DWORDAlignedSize(recordSize) - 2))); // don't include size of 'length' in 'length'
_blob.WriteLeafKind(LeafKind.LF_POINTER);
_blob.WriteDWORD(pointerTypeDescriptor.ElementType);
_blob.WriteDWORD(attr);
VerifyBlobEligibleToBeBetweenRecords();
return pointerTypeIndex;
}
public uint GetSimpleArrayTypeIndex(uint elementType, uint elementSize)
{
uint simpleArrayTypeIndex = _blob.GetNextTypeIndex();
TypeRecordsBlob simpleArrayDataBlob = new TypeRecordsBlob();
simpleArrayDataBlob.WriteLeafKind(LeafKind.LF_ARRAY);
simpleArrayDataBlob.WriteDWORD(elementType);
simpleArrayDataBlob.WriteDWORD((uint)PrimitiveTypeDescriptor.TYPE_ENUM.T_INT4);
simpleArrayDataBlob.WriteNumericLeaf(elementSize);
simpleArrayDataBlob.WriteString("");
uint recordSize = simpleArrayDataBlob.Size() + 2;
_blob.WriteWORD(checked((ushort)(_blob.DWORDAlignedSize(recordSize) - 2))); // don't include size of 'length' in 'length'
_blob.WriteBuffer(simpleArrayDataBlob);
_blob.AlignToDWORD();
VerifyBlobEligibleToBeBetweenRecords();
return simpleArrayTypeIndex;
}
public uint GetArrayTypeIndex(ClassTypeDescriptor classDescriptor, ArrayTypeDescriptor arrayTypeDescriptor, int targetPointerSize)
{
uint simpleArrayDebugType = GetSimpleArrayTypeIndex(arrayTypeDescriptor.ElementType, arrayTypeDescriptor.Size);
FieldListInProgress fieldList = default(FieldListInProgress);
fieldList = StartFieldList();
EmitBaseClass(ref fieldList, classDescriptor.BaseClassId);
EmitDataMember(ref fieldList, (uint)PrimitiveTypeDescriptor.TYPE_ENUM.T_INT4, targetPointerSize, new Utf8String("count"));
int nextOffset = targetPointerSize * 2;
if (arrayTypeDescriptor.IsMultiDimensional != 0)
{
for (uint i = 0; i < arrayTypeDescriptor.Rank; i++)
{
EmitDataMember(ref fieldList, (uint)PrimitiveTypeDescriptor.TYPE_ENUM.T_INT4, nextOffset, new Utf8String("length" + i.ToStringInvariant()));
nextOffset += 4;
}
for (uint i = 0; i < arrayTypeDescriptor.Rank; i++)
{
EmitDataMember(ref fieldList, (uint)PrimitiveTypeDescriptor.TYPE_ENUM.T_INT4, nextOffset, new Utf8String("bounds" + i.ToStringInvariant()));
nextOffset += 4;
}
}
EmitDataMember(ref fieldList, simpleArrayDebugType, nextOffset, new Utf8String("values"));
FinalizeFieldList(fieldList);
uint classTypeIndex = _blob.GetNextTypeIndex();
Utf8String name = new Utf8String(classDescriptor.Name);
uint recordSize = 20 + DebugInfoBlob.StringLengthEncoded(name) + TypeRecordsBlob.NumericLeafSize(targetPointerSize) /*size of length */;
_blob.WriteWORD(checked((ushort)(_blob.DWORDAlignedSize(recordSize) - 2))); // don't include size of 'length' in 'length'
_blob.WriteLeafKind(classDescriptor.IsStruct != 0 ? LeafKind.LF_STRUCTURE : LeafKind.LF_CLASS);
_blob.WriteWORD(fieldList.FieldsCount);
_blob.WriteLF_CLASS_Properties(LF_CLASS_Properties.None);
_blob.WriteDWORD(fieldList.TypeIndexOfFieldList);
_blob.WriteDWORD(0); // Derivation list is not filled in here
_blob.WriteDWORD(_tiVTShapePointer); // No vtable shape
_blob.WriteNumericLeaf(targetPointerSize);
_blob.WriteString(name);
_blob.AlignToDWORD();
VerifyBlobEligibleToBeBetweenRecords();
return classTypeIndex;
}
public DebugInfoBlob GetRawBlob()
{
return _blob;
}
}
}

Просмотреть файл

@ -0,0 +1,14 @@
// 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.
namespace ILCompiler.DependencyAnalysis
{
public interface IMethodBodyNodeWithFuncletSymbols : IMethodBodyNode
{
/// <summary>
/// Symbols of any funclets associated with this method.
/// </summary>
ISymbolNode[] FuncletSymbols { get; }
}
}

Просмотреть файл

@ -0,0 +1,19 @@
// 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 ILCompiler.DependencyAnalysisFramework;
using Internal.Text;
namespace ILCompiler.DependencyAnalysis
{
/// <summary>
/// Represents a reference to a symbol attributed with a funclet id.
/// </summary>
public interface ISymbolNodeWithFuncletId : ISymbolNode
{
ISymbolNode AssociatedMethodSymbol { get; }
int FuncletId { get; }
}
}

Просмотреть файл

@ -0,0 +1,108 @@
// 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.Diagnostics;
using Internal.TypeSystem.TypesDebugInfo;
using ILCompiler.DependencyAnalysisFramework;
namespace ILCompiler.DependencyAnalysis
{
// Part of Node factory that deals with nodes describing windows debug data
partial class NodeFactory
{
/// <summary>
/// Helper class that provides a level of grouping for all the windows debug data nodes
/// </summary>
public class WindowsDebugDataHelper
{
NodeFactory _nodeFactory;
public WindowsDebugDataHelper(NodeFactory nodeFactory)
{
_nodeFactory = nodeFactory;
}
/// <summary>
/// Initialize the WindowsDebugData emission pipeline.
/// Cannot be called twice
/// </summary>
/// <param name="nonSectionBasedDebugInfoWriter">debug$T section generation interface. If null, use managed implementation that generates a object file section.</param>
/// <param name="mergedAssemblyRecords">record of how assemblies are merged. If null, do not genearate extended debug information</param>
/// <param name="graph">Graph to attach WindowsDebugData to</param>
public void Init(ITypesDebugInfoWriter nonSectionBasedDebugInfoWriter, MergedAssemblyRecords mergedAssemblyRecords, DependencyAnalyzerBase<NodeFactory> graph)
{
Debug.Assert(_userDefinedTypeDescriptor == null); // Cannot be called twice
Debug.Assert(graph != null);
_debugNeedTypeIndicesStore = new WindowsDebugNeedTypeIndicesStoreNode();
if (mergedAssemblyRecords != null)
{
_debugPseudoAssemblySection = new WindowsDebugPseudoAssemblySection(_nodeFactory.TypeSystemContext);
_debugMergedAssembliesSection = new WindowsDebugMergedAssembliesSection(mergedAssemblyRecords);
_debugILImagesSection = new WindowsDebugILImagesSection(mergedAssemblyRecords);
_debugManagedNativeDictionaryInfoSection = new WindowsDebugManagedNativeDictionaryInfoSection();
}
bool is64Bit = _nodeFactory.Target.PointerSize == 8 ? true : false;
if (nonSectionBasedDebugInfoWriter != null)
{
_userDefinedTypeDescriptor = new UserDefinedTypeDescriptor(nonSectionBasedDebugInfoWriter, is64Bit, _nodeFactory.Target.Abi);
}
else
{
_debugTypeRecordsSection = new WindowsDebugTypeRecordsSection(new DebugInfoWriter(), _nodeFactory);
_userDefinedTypeDescriptor = new UserDefinedTypeDescriptor(_debugTypeRecordsSection, is64Bit, _nodeFactory.Target.Abi);
}
if (mergedAssemblyRecords != null)
{
_debugTypeSignatureMapSection = new WindowsDebugTypeSignatureMapSection(_userDefinedTypeDescriptor);
_debugMethodSignatureMapSection = new WindowsDebugMethodSignatureMapSection();
}
graph.AddRoot(_debugNeedTypeIndicesStore, "Debug Force All EETypes to have type indices");
if (_debugManagedNativeDictionaryInfoSection != null)
graph.AddRoot(_debugManagedNativeDictionaryInfoSection, "Debug Method MDToken map");
if (_debugMethodSignatureMapSection != null)
graph.AddRoot(_debugMethodSignatureMapSection, "Debug Method MDToken map");
if (_debugTypeSignatureMapSection != null)
graph.AddRoot(_debugTypeSignatureMapSection, "Debug Type MDToken map");
if (_debugILImagesSection != null)
graph.AddRoot(_debugILImagesSection, "Debug Merged ILImages");
if (_debugMergedAssembliesSection != null)
graph.AddRoot(_debugMergedAssembliesSection, "Debug MergedAssemblyRecords");
if (_debugPseudoAssemblySection != null)
graph.AddRoot(_debugPseudoAssemblySection, "Debug PseudoAssembly");
if (_debugTypeRecordsSection != null)
graph.AddRoot(_debugTypeRecordsSection, "Debug Type Records");
}
private WindowsDebugILImagesSection _debugILImagesSection;
private WindowsDebugTypeSignatureMapSection _debugTypeSignatureMapSection;
private WindowsDebugTypeRecordsSection _debugTypeRecordsSection;
private WindowsDebugManagedNativeDictionaryInfoSection _debugManagedNativeDictionaryInfoSection;
private WindowsDebugMethodSignatureMapSection _debugMethodSignatureMapSection;
private WindowsDebugMergedAssembliesSection _debugMergedAssembliesSection;
private WindowsDebugPseudoAssemblySection _debugPseudoAssemblySection;
private UserDefinedTypeDescriptor _userDefinedTypeDescriptor;
private WindowsDebugNeedTypeIndicesStoreNode _debugNeedTypeIndicesStore;
internal WindowsDebugILImagesSection DebugILImagesSection => _debugILImagesSection;
internal WindowsDebugTypeSignatureMapSection DebugTypeSignatureMapSection => _debugTypeSignatureMapSection;
internal WindowsDebugMethodSignatureMapSection DebugMethodSignatureMapSection => _debugMethodSignatureMapSection;
internal WindowsDebugTypeRecordsSection DebugTypeRecordsSection => _debugTypeRecordsSection;
internal WindowsDebugMergedAssembliesSection DebugMergedAssembliesSection => _debugMergedAssembliesSection;
internal WindowsDebugPseudoAssemblySection DebugPseudoAssemblySection => _debugPseudoAssemblySection;
internal WindowsDebugManagedNativeDictionaryInfoSection DebugManagedNativeDictionaryInfoSection => _debugManagedNativeDictionaryInfoSection;
internal WindowsDebugNeedTypeIndicesStoreNode DebugNeedTypeIndicesStore => _debugNeedTypeIndicesStore;
public UserDefinedTypeDescriptor UserDefinedTypeDescriptor => _userDefinedTypeDescriptor;
}
public WindowsDebugDataHelper WindowsDebugData { get; private set; }
}
}

Просмотреть файл

@ -479,6 +479,7 @@ namespace ILCompiler.DependencyAnalysis
});
NativeLayout = new NativeLayoutHelper(this);
WindowsDebugData = new WindowsDebugDataHelper(this);
}
protected abstract IMethodNode CreateMethodEntrypointNode(MethodDesc method);

Просмотреть файл

@ -2,10 +2,12 @@
// 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.DependencyAnalysisFramework;
using Internal.Text;
using Internal.TypeSystem;
namespace ILCompiler.DependencyAnalysis
@ -15,10 +17,11 @@ namespace ILCompiler.DependencyAnalysis
/// in the DependencyAnalysis infrastructure during compilation that is compiled
/// in the current compilation process
/// </summary>
public class NonExternMethodSymbolNode : ExternSymbolNode, IMethodNode
public class NonExternMethodSymbolNode : ExternSymbolNode, IMethodBodyNodeWithFuncletSymbols
{
private MethodDesc _method;
private List<DependencyListEntry> _compilationDiscoveredDependencies;
ISymbolNode[] _funcletSymbols = Array.Empty<ISymbolNode>();
bool _dependenciesQueried;
bool _hasCompiledBody;
@ -29,6 +32,8 @@ namespace ILCompiler.DependencyAnalysis
_method = method;
}
protected override string GetName(NodeFactory factory) => "Non" + base.GetName(factory);
public MethodDesc Method
{
get
@ -45,6 +50,16 @@ namespace ILCompiler.DependencyAnalysis
_hasCompiledBody = true;
}
public void SetFuncletCount(int funcletCount)
{
Debug.Assert(funcletCount > 0);
Debug.Assert(_funcletSymbols.Length == 0);
ISymbolNode[] funclets = new ISymbolNode[funcletCount];
for (int funcletId = 1; funcletId <= funcletCount; funcletId++)
funclets[funcletId - 1] = new FuncletSymbol(this, funcletId);
_funcletSymbols = funclets;
}
public void AddCompilationDiscoveredDependency(IDependencyNode<NodeFactory> node, string reason)
{
Debug.Assert(!_dependenciesQueried);
@ -64,6 +79,14 @@ namespace ILCompiler.DependencyAnalysis
}
}
ISymbolNode[] IMethodBodyNodeWithFuncletSymbols.FuncletSymbols
{
get
{
return _funcletSymbols;
}
}
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
{
_dependenciesQueried = true;
@ -78,5 +101,49 @@ namespace ILCompiler.DependencyAnalysis
return dependencies;
}
private class FuncletSymbol : ISymbolNodeWithFuncletId
{
public FuncletSymbol(NonExternMethodSymbolNode methodSymbol, int funcletId)
{
_funcletId = funcletId;
_methodSymbol = methodSymbol;
}
private int _funcletId;
private NonExternMethodSymbolNode _methodSymbol;
public ISymbolNode AssociatedMethodSymbol => _methodSymbol;
public int FuncletId => _funcletId;
public int Offset => 0;
public bool RepresentsIndirectionCell => false;
public bool InterestingForDynamicDependencyAnalysis => false;
public bool HasDynamicDependencies => false;
public bool HasConditionalStaticDependencies => false;
public bool StaticDependenciesAreComputed => true;
public bool Marked => _methodSymbol.Marked;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
_methodSymbol.AppendMangledName(nameMangler, sb);
}
public IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context)
{
return null;
}
public IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context)
{
return null;
}
public IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context)
{
return null;
}
}
}
}

Просмотреть файл

@ -90,6 +90,14 @@ namespace ILCompiler.DependencyAnalysis
EmitByte((byte)((emit >> 24) & 0xFF));
}
public void EmitUInt(uint emit)
{
EmitByte((byte)(emit & 0xFF));
EmitByte((byte)((emit >> 8) & 0xFF));
EmitByte((byte)((emit >> 16) & 0xFF));
EmitByte((byte)((emit >> 24) & 0xFF));
}
public void EmitLong(long emit)
{
EmitByte((byte)(emit & 0xFF));
@ -169,6 +177,11 @@ namespace ILCompiler.DependencyAnalysis
_data.Append(bytes, offset, length);
}
internal void EmitBytes(ArrayBuilder<byte> bytes)
{
_data.Append(bytes);
}
public void EmitZeroPointer()
{
_data.ZeroExtend(_target.PointerSize);

Просмотреть файл

@ -0,0 +1,98 @@
// 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.Diagnostics;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;
using Internal.Text;
namespace ILCompiler.DependencyAnalysis
{
internal class WindowsDebugILImagesSection : ObjectNode, ISymbolDefinitionNode
{
private MergedAssemblyRecords _mergedAssemblies;
public WindowsDebugILImagesSection(MergedAssemblyRecords mergedAssemblies)
{
_mergedAssemblies = mergedAssemblies;
}
private ObjectNodeSection _section = new ObjectNodeSection(".ilimges", SectionType.ReadOnly);
public override ObjectNodeSection Section => _section;
public override bool IsShareable => false;
public override bool StaticDependenciesAreComputed => true;
public int Offset => 0;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(GetName(null));
}
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 });
MemoryStream memoryStream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(memoryStream, Encoding.Unicode, true);
writer.Write(1); // magic format version number
writer.Write(_mergedAssemblies.MergedAssemblies.Count); // number of il images that will follow
int totalSizeOfActualMergedAssemblies = 0;
checked
{
const int ILIMAGES_HEADER_ELEMENTS = 2;
const int ILIMAGES_PERMODULE_ELEMENTS = 3;
int endOfILAssemblyListHeader = ((_mergedAssemblies.MergedAssemblies.Count * ILIMAGES_PERMODULE_ELEMENTS) + ILIMAGES_HEADER_ELEMENTS) * sizeof(int);
int offsetOfNextAssembly = endOfILAssemblyListHeader;
foreach (MergedAssemblyRecord mergedAssembly in _mergedAssemblies.MergedAssemblies)
{
int assemblyFileLen = mergedAssembly.Assembly.PEReader.GetEntireImage().Length;
writer.Write(mergedAssembly.AssemblyIndex);
writer.Write(offsetOfNextAssembly);
writer.Write(assemblyFileLen);
offsetOfNextAssembly += assemblyFileLen;
totalSizeOfActualMergedAssemblies += assemblyFileLen;
}
writer.Flush();
writer.Dispose();
byte[] mergedAssemblyHeader = memoryStream.ToArray();
Debug.Assert(mergedAssemblyHeader.Length == endOfILAssemblyListHeader);
byte[] mergedAssemblyBlob = new byte[mergedAssemblyHeader.Length + totalSizeOfActualMergedAssemblies];
Array.Copy(mergedAssemblyHeader, mergedAssemblyBlob, mergedAssemblyHeader.Length);
offsetOfNextAssembly = endOfILAssemblyListHeader;
foreach (MergedAssemblyRecord mergedAssembly in _mergedAssemblies.MergedAssemblies)
{
var memoryBlock = mergedAssembly.Assembly.PEReader.GetEntireImage();
int assemblyFileLen = memoryBlock.Length;
unsafe
{
Marshal.Copy(new IntPtr(memoryBlock.Pointer), mergedAssemblyBlob, offsetOfNextAssembly, assemblyFileLen);
}
offsetOfNextAssembly += assemblyFileLen;
}
return new ObjectData(mergedAssemblyBlob, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
}
}
protected override string GetName(NodeFactory context)
{
return "___DebugILImagesSection";
}
}
}

Просмотреть файл

@ -0,0 +1,105 @@
// 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.Collections.Concurrent;
using System.Diagnostics;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using Internal.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.TypesDebugInfo;
namespace ILCompiler.DependencyAnalysis
{
internal class WindowsDebugManagedNativeDictionaryInfoSection : ObjectNode, ISymbolDefinitionNode
{
public WindowsDebugManagedNativeDictionaryInfoSection()
{
}
private ObjectNodeSection _section = new ObjectNodeSection(".dbgmanagednativedictionaryinfo", SectionType.ReadOnly);
public override ObjectNodeSection Section => _section;
public override bool IsShareable => false;
public override bool StaticDependenciesAreComputed => true;
public int Offset => 0;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(GetName(null));
}
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 });
ObjectDataBuilder objDataBuilder = new ObjectDataBuilder(factory, relocsOnly);
// Emit number of dictionaries in table
objDataBuilder.AddSymbol(this);
IReadOnlyCollection<GenericDictionaryNode> dictionariesEmitted = factory.MetadataManager.GetCompiledGenericDictionaries();
objDataBuilder.EmitInt(dictionariesEmitted.Count);
DebugInfoBlob signatureData = new DebugInfoBlob();
BlobBuilder signatureBlobBuilder = new BlobBuilder();
BlobBuilder signatureLenBuilder = new BlobBuilder();
ManagedBinaryEmitter pseudoAssembly = factory.WindowsDebugData.DebugPseudoAssemblySection.PseudoAssembly;
foreach (GenericDictionaryNode dictionary in dictionariesEmitted)
{
objDataBuilder.EmitReloc(dictionary, RelocType.IMAGE_REL_BASED_ADDR32NB);
objDataBuilder.EmitUInt(signatureData.Size());
signatureBlobBuilder.Clear();
int typeDictLen = dictionary.TypeInstantiation.IsNull ? 0 : dictionary.TypeInstantiation.Length;
int methodDictLen = dictionary.MethodInstantiation.IsNull ? 0 : dictionary.MethodInstantiation.Length;
signatureBlobBuilder.WriteCompressedInteger(typeDictLen + methodDictLen);
if (typeDictLen != 0)
{
foreach (TypeDesc type in dictionary.TypeInstantiation)
{
pseudoAssembly.EncodeSignatureForType(type, signatureBlobBuilder);
}
}
if (methodDictLen != 0)
{
foreach (TypeDesc type in dictionary.MethodInstantiation)
{
pseudoAssembly.EncodeSignatureForType(type, signatureBlobBuilder);
}
}
int blobSize = signatureBlobBuilder.Count;
signatureLenBuilder.Clear();
signatureLenBuilder.WriteCompressedInteger(blobSize);
// Prepend the signature data with a length
signatureData.WriteBuffer(signatureLenBuilder);
// And then attach the actual signature data
signatureData.WriteBuffer(signatureBlobBuilder);
}
// Attach signature information to end after all of the rva/offset pairs
objDataBuilder.EmitBytes(signatureData.ToArray());
return objDataBuilder.ToObjectData();
}
protected override string GetName(NodeFactory context)
{
return "___DebugManagedNativeDictionaryInfoSection";
}
}
}

Просмотреть файл

@ -0,0 +1,60 @@
// 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.Diagnostics;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;
using Internal.Text;
using Internal.TypeSystem.TypesDebugInfo;
namespace ILCompiler.DependencyAnalysis
{
internal class WindowsDebugMergedAssembliesSection : ObjectNode, ISymbolDefinitionNode
{
private MergedAssemblyRecords _mergedAssemblies;
public WindowsDebugMergedAssembliesSection(MergedAssemblyRecords mergedAssemblies)
{
_mergedAssemblies = mergedAssemblies;
}
private ObjectNodeSection _section = new ObjectNodeSection(".dbgmergedassemblyrecords", SectionType.ReadOnly);
public override ObjectNodeSection Section => _section;
public override bool IsShareable => false;
public override bool StaticDependenciesAreComputed => true;
public int Offset => 0;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(GetName(null));
}
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 });
DebugInfoBlob debugBlob = new DebugInfoBlob();
foreach (MergedAssemblyRecord record in _mergedAssemblies.MergedAssemblies)
record.Encode(debugBlob);
byte [] _pdbBlob = debugBlob.ToArray();
Debug.Assert(_pdbBlob.Length > 0);
return new ObjectData(_pdbBlob, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
}
protected override string GetName(NodeFactory context)
{
return "___DebugMergedAssemblyRecordsSection";
}
}
}

Просмотреть файл

@ -0,0 +1,187 @@
// 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.Collections.Concurrent;
using System.Diagnostics;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using Internal.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.TypesDebugInfo;
namespace ILCompiler.DependencyAnalysis
{
internal class WindowsDebugMethodSignatureMapSection : ObjectNode, ISymbolDefinitionNode
{
public WindowsDebugMethodSignatureMapSection()
{
}
private ObjectNodeSection _section = new ObjectNodeSection(".dbgmethodsignaturemap", SectionType.ReadOnly);
public override ObjectNodeSection Section => _section;
public override bool IsShareable => false;
public override bool StaticDependenciesAreComputed => true;
public int Offset => 0;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(GetName(null));
}
struct EmittedMethodWithILToken : IComparable<EmittedMethodWithILToken>
{
public EmittedMethodWithILToken(IMethodBodyNode emittedMethod, uint ilTokenRid)
{
EmittedMethod = emittedMethod;
IlTokenRid = ilTokenRid;
}
public IMethodBodyNode EmittedMethod;
public uint IlTokenRid;
int IComparable<EmittedMethodWithILToken>.CompareTo(EmittedMethodWithILToken other)
{
if (other.IlTokenRid == IlTokenRid)
return 0;
if (other.IlTokenRid < IlTokenRid)
return -1;
return 1;
}
}
//
// returns the DEBUG_S_FUNC_MDTOKEN_MAP subsection as a byte array
// DEBUG_S_FUNC_MDTOKEN_MAP subsection contains method RVA to mdToken mapping
//
// contents of subsection:
// offset 0, 4 bytes: count of entries in the map
// offset 4, 8*N bytes: 4 byte RVA + 4 byte 'offset' relative to the start of 'method data'
// offset 4+8*N, * bytes: all method data packed sequentially with no padding. method data consists of
// 1 byte 'count' of generic parameters, 3 bytes of method's rid and 'count'
// variable sized ECMA formatted TypeSpec signatures for each generic parameter
//
// Compiler places the CTLToken (for a method) or the lexical funclet order (if a method has 1 or more funclets),
// which binder uses to compute the RVA.
//
// all entries are sorted by 'offset' field.
//
// 'offset' optimization: if the method has no generic parameters, we don't need to pass in a signature
// and can encode the mdToken of method in 'offset'
// We do this by setting the high bit of 'offset' and then storing rid part of
// token in last 3 bytes of 'offset'
//
internal DebugInfoBlob GetDebugMethodRVAToTokenMap(ManagedBinaryEmitter pseudoAssembly, IEnumerable<IMethodBodyNode> emittedMethods, out List<Relocation> debugRelocations)
{
DebugInfoBlob methodRVAToTokenMap = new DebugInfoBlob();
DebugInfoBlob methodDataBlob = new DebugInfoBlob();
debugRelocations = new List<Relocation>();
BlobBuilder blobBuilder = new BlobBuilder();
uint entryCount = 0;
methodRVAToTokenMap.WriteDWORD(0); // Placeholder for count of entries in map. Will be udpated later.
List<EmittedMethodWithILToken> tokenInOffsetEntries = new List<EmittedMethodWithILToken>();
foreach (IMethodBodyNode emitted in emittedMethods)
{
if (!(emitted.Method.GetMethodDefinition() is Internal.TypeSystem.Ecma.EcmaMethod))
{
continue;
}
EntityHandle methodHandle = pseudoAssembly.EmitMetadataHandleForTypeSystemEntity(emitted.Method.GetMethodDefinition());
Debug.Assert(methodHandle.Kind == HandleKind.MemberReference);
uint methodToken = (uint)MetadataTokens.GetToken(methodHandle);
uint methodTokenRid = methodToken & 0xFFFFFF;
if (!(emitted.Method.HasInstantiation || emitted.Method.OwningType.HasInstantiation))
{
tokenInOffsetEntries.Add(new EmittedMethodWithILToken(emitted, methodTokenRid));
continue;
}
uint cGenericArguments = checked((uint)emitted.Method.Instantiation.Length + (uint)emitted.Method.OwningType.Instantiation.Length);
// Debugger format does not allow the debugging of methods that have more than 255 generic parameters (spread between the type and method instantiation)
if (cGenericArguments > 0xFF)
continue;
blobBuilder.Clear();
// write the signature for each generic parameter of class
foreach (TypeDesc instantiationType in emitted.Method.OwningType.Instantiation)
pseudoAssembly.EncodeSignatureForType(instantiationType, blobBuilder);
// write the signature for each generic parameter of the method
foreach (TypeDesc instantiationType in emitted.Method.Instantiation)
pseudoAssembly.EncodeSignatureForType(instantiationType, blobBuilder);
Add_DEBUG_S_FUNC_MDTOKEN_MAP_Entry(methodRVAToTokenMap, debugRelocations, emitted, methodDataBlob.Size(), ref entryCount);
methodDataBlob.WriteDWORD(cGenericArguments << 24 | methodTokenRid);
methodDataBlob.WriteBuffer(blobBuilder);
}
// sort tokenInOffsetEntries based on tokenInOffset
tokenInOffsetEntries.Sort();
foreach (EmittedMethodWithILToken emitted in tokenInOffsetEntries)
{
Add_DEBUG_S_FUNC_MDTOKEN_MAP_Entry(methodRVAToTokenMap, debugRelocations, emitted.EmittedMethod, emitted.IlTokenRid | 0x80000000, ref entryCount);
}
methodRVAToTokenMap.SetDWORDAtBlobIndex(0, entryCount); // // Update placeholder for count of entries in map
methodRVAToTokenMap.WriteBuffer(methodDataBlob);
return methodRVAToTokenMap;
}
private void Add_DEBUG_S_FUNC_MDTOKEN_MAP_Entry(DebugInfoBlob methodRVAToTokenMap, List<Relocation> debugRelocations, IMethodBodyNode method, uint methodDataOrOffsetToMethodData, ref uint entryCount)
{
debugRelocations.Add(new Relocation(RelocType.IMAGE_REL_BASED_ADDR32NB, checked((int)methodRVAToTokenMap.Size()), method));
methodRVAToTokenMap.WriteDWORD(0);
methodRVAToTokenMap.WriteDWORD(methodDataOrOffsetToMethodData);
entryCount++;
IMethodBodyNodeWithFuncletSymbols funcletSymbolsNode = method as IMethodBodyNodeWithFuncletSymbols;
if (funcletSymbolsNode != null)
{
foreach (ISymbolNode funclet in funcletSymbolsNode.FuncletSymbols)
{
debugRelocations.Add(new Relocation(RelocType.IMAGE_REL_BASED_ADDR32NB, checked((int)methodRVAToTokenMap.Size()), funclet));
methodRVAToTokenMap.WriteDWORD(0);
methodRVAToTokenMap.WriteDWORD(methodDataOrOffsetToMethodData);
entryCount++;
}
}
}
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 });
if (factory.WindowsDebugData.DebugTypeRecordsSection != null)
factory.WindowsDebugData.DebugTypeRecordsSection.Neuter();
List<Relocation> relocations = new List<Relocation>();
DebugInfoBlob debugData = GetDebugMethodRVAToTokenMap(factory.WindowsDebugData.DebugPseudoAssemblySection.PseudoAssembly, factory.MetadataManager.GetCompiledMethodBodies(), out relocations);
return new ObjectData(debugData.ToArray(), relocations.ToArray(), 1, new ISymbolDefinitionNode[] { this });
}
protected override string GetName(NodeFactory context)
{
return "___DebugMethodSignatureMapSection";
}
}
}

Просмотреть файл

@ -0,0 +1,68 @@
// 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.Linq;
using System.Collections.Generic;
using Internal.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.TypesDebugInfo;
namespace ILCompiler.DependencyAnalysis
{
public class WindowsDebugNeedTypeIndicesStoreNode : ObjectNode, ISymbolDefinitionNode
{
public override ObjectNodeSection Section => ObjectNodeSection.DataSection;
public override bool IsShareable => true;
public override bool StaticDependenciesAreComputed => true;
public int Offset => 0;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(GetName(null));
}
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
if (!relocsOnly)
{
UserDefinedTypeDescriptor userDefinedTypeDescriptor = factory.WindowsDebugData.UserDefinedTypeDescriptor;
if (userDefinedTypeDescriptor != null)
{
List<TypeDesc> typesThatNeedIndices = new List<TypeDesc>();
foreach (TypeDesc type in factory.MetadataManager.GetTypesWithEETypes())
{
if (!type.IsGenericDefinition)
{
typesThatNeedIndices.Add(type);
}
}
typesThatNeedIndices.Sort(new TypeSystemComparer().Compare);
foreach (TypeDesc type in typesThatNeedIndices)
{
// Force creation of type descriptors for _ALL_ EETypes
userDefinedTypeDescriptor.GetVariableTypeIndex(type);
}
}
}
// There isn't actually any data in this node. Its simply an ObjectNode as that allows this
// function to be executed in a defined time during object emission. This does imply embedding a bit of data
// into the object file, but the linker should be able to strip it out of the final file, and even if its in the final file
// it won't cost significant size.
return new ObjectData(new byte[1], Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
}
protected override string GetName(NodeFactory context)
{
return "___DebugNeedTypeIndicesStore";
}
}
}

Просмотреть файл

@ -0,0 +1,54 @@
// 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.IO;
using Internal.Text;
using Internal.TypeSystem;
namespace ILCompiler.DependencyAnalysis
{
public class WindowsDebugPseudoAssemblySection : ObjectNode, ISymbolDefinitionNode
{
private ManagedBinaryEmitter _pseudoAssembly;
public WindowsDebugPseudoAssemblySection(TypeSystemContext typeSystemContext)
{
_pseudoAssembly = new ManagedBinaryEmitter(typeSystemContext, "PseudoAssembly");
}
private ObjectNodeSection _section = new ObjectNodeSection(".psdo-il", SectionType.ReadOnly);
public override ObjectNodeSection Section => _section;
public ManagedBinaryEmitter PseudoAssembly => _pseudoAssembly;
public override bool IsShareable => false;
public override bool StaticDependenciesAreComputed => true;
public int Offset => 0;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(GetName(null));
}
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 });
MemoryStream memoryStream = new MemoryStream(1000000);
_pseudoAssembly.EmitToStream(memoryStream);
_pseudoAssembly = null;
return new ObjectData(memoryStream.ToArray(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
}
protected override string GetName(NodeFactory context)
{
return "___DebugPseudoAssemblySection";
}
}
}

Просмотреть файл

@ -0,0 +1,105 @@
// 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.Concurrent;
using System.Diagnostics;
using Internal.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.TypesDebugInfo;
namespace ILCompiler.DependencyAnalysis
{
internal class WindowsDebugTypeRecordsSection : ObjectNode, ISymbolDefinitionNode, ITypesDebugInfoWriter
{
DebugInfoWriter _dbgInfo; // Pointer to DebugInfoWriter used to write data
DebugInfoWriter _dbgInfoWriter; // Pointer to DebugInfoWriter used to generate new entries
NodeFactory _nodeFactory;
public WindowsDebugTypeRecordsSection(DebugInfoWriter dbgInfo, NodeFactory factory)
{
_dbgInfoWriter = _dbgInfo = dbgInfo;
_nodeFactory = factory;
}
private ObjectNodeSection _section = new ObjectNodeSection(".debug$T", SectionType.ReadOnly);
public override ObjectNodeSection Section => _section;
public override bool IsShareable => false;
public override bool StaticDependenciesAreComputed => true;
public int Offset => 0;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(GetName(null));
}
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 });
Debug.Assert(_dbgInfoWriter == null); // Type records should all be written and writing shutdown before reaching this point
byte[] typeRecords = _dbgInfo.GetRawBlob().ToArray();
_dbgInfo = null; // Neuter the section so that it cannot grow any larger
return new ObjectData(typeRecords, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
}
protected override string GetName(NodeFactory context)
{
return "___DebugTypeRecordsSection";
}
public void Neuter()
{
_dbgInfoWriter = null;
}
uint ITypesDebugInfoWriter.GetEnumTypeIndex(EnumTypeDescriptor enumTypeDescriptor, EnumRecordTypeDescriptor[] typeRecords)
{
return _dbgInfoWriter.GetEnumTypeIndex(enumTypeDescriptor, typeRecords);
}
uint ITypesDebugInfoWriter.GetClassTypeIndex(ClassTypeDescriptor classTypeDescriptor)
{
return _dbgInfoWriter.GetClassTypeIndex(classTypeDescriptor);
}
uint ITypesDebugInfoWriter.GetCompleteClassTypeIndex(ClassTypeDescriptor classTypeDescriptor, ClassFieldsTypeDescriptor classFieldsTypeDescriptior, DataFieldDescriptor[] fields)
{
return _dbgInfoWriter.GetCompleteClassTypeIndex(classTypeDescriptor, classFieldsTypeDescriptior, fields);
}
uint ITypesDebugInfoWriter.GetArrayTypeIndex(ClassTypeDescriptor classDescriptor, ArrayTypeDescriptor arrayTypeDescriptor)
{
return _dbgInfoWriter.GetArrayTypeIndex(classDescriptor, arrayTypeDescriptor, _nodeFactory.Target.PointerSize);
}
uint ITypesDebugInfoWriter.GetPointerTypeIndex(PointerTypeDescriptor pointerDescriptor)
{
return _dbgInfoWriter.GetPointerTypeIndex(pointerDescriptor);
}
uint ITypesDebugInfoWriter.GetMemberFunctionTypeIndex(MemberFunctionTypeDescriptor memberDescriptor, uint[] argumentTypes)
{
return _dbgInfoWriter.GetMemberFunctionTypeIndex(memberDescriptor, argumentTypes);
}
uint ITypesDebugInfoWriter.GetMemberFunctionId(MemberFunctionIdTypeDescriptor memberIdDescriptor)
{
return _dbgInfoWriter.GetMemberFunctionId(memberIdDescriptor);
}
string ITypesDebugInfoWriter.GetMangledName(TypeDesc type)
{
return _nodeFactory.NameMangler.GetMangledTypeName(type);
}
}
}

Просмотреть файл

@ -0,0 +1,143 @@
// 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.IO;
using System.Reflection.Metadata;
using Internal.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.TypesDebugInfo;
namespace ILCompiler.DependencyAnalysis
{
internal class WindowsDebugTypeSignatureMapSection : ObjectNode, ISymbolDefinitionNode
{
UserDefinedTypeDescriptor _userDefinedTypeDescriptor;
public WindowsDebugTypeSignatureMapSection(UserDefinedTypeDescriptor userDefinedTypeDescriptor)
{
_userDefinedTypeDescriptor = userDefinedTypeDescriptor;
}
private ObjectNodeSection _section = new ObjectNodeSection(".dbgtypesignaturemap", SectionType.ReadOnly);
public override ObjectNodeSection Section => _section;
public override bool IsShareable => false;
public override bool StaticDependenciesAreComputed => true;
public int Offset => 0;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(GetName(null));
}
// returns the DEBUG_S_TYPE_MDTOKEN_MAP subsection as a byte array
// DEBUG_S_TYPE_MDTOKEN_MAP subsection contains type-index to mdToken mapping
//
// contents of subsection:
// offset 0, 4 bytes: count of entries in the map
// offset 4, 8*N bytes: 4 byte type-index + 4 byte 'offset' relative to the start of 'type data'
// offset 4+8*N, * bytes: ECMA formatted type signature packed sequentially with no padding
//
// 'offset' optimization: for type signatures with size<= 4-bytes
// we can store the signature in offset field such that
// offset = (1 << 31) | (sig[0] << 24 | sig[1] << 16 | sig[2] << 8 | sig[3])
// We chose this bit encoding because sig[0] holds the CorElementType whose
// highest bit is always 0 and the highest bit of offset can be used as a flag
// to indicate that it is not an offset but the signature itself.
//
// all entries are sorted by 'offset' field and so offset-based entries are arranged before other
// (raw-signature) entries (since raw-signature entries are of the form 0x80000000 | signature, and will always be
// numerically bigger than the offset)
//
private DebugInfoBlob GetDebugTypeIndexToTokenMap(ManagedBinaryEmitter pseudoAssembly, ICollection<KeyValuePair<TypeDesc, uint>> completeKnownTypes)
{
DebugInfoBlob typeDataBlob = new DebugInfoBlob();
DebugInfoBlob typeIndexToTokenMapBlob = new DebugInfoBlob();
List<KeyValuePair<uint, uint>> sigInOffsetEntries = new List<KeyValuePair<uint, uint>>();
typeIndexToTokenMapBlob.WriteDWORD(checked((uint)completeKnownTypes.Count));
BlobBuilder blobBuilder = new BlobBuilder();
foreach (var entry in completeKnownTypes)
{
uint typeIndex = entry.Value;
blobBuilder.Clear();
pseudoAssembly.EncodeSignatureForType(entry.Key, blobBuilder);
// if signature fits in 4-bytes, store it in sigInOffsetEntries
// otherwise store it in the type-data blob
if (blobBuilder.Count <= 4)
{
uint sigInOffset = 0x80000000;
int i = 0;
// This is a slightly confusing approach, but this is how one iterates through the bytes in a blobBuilder without flattening it to a byte[]
foreach (Blob blob in blobBuilder.GetBlobs())
{
foreach (byte b in blob.GetBytes())
{
sigInOffset |= ((uint)b) << (8 * (3 - i));
i++;
}
}
// sigInOffsetEntries will be later sorted and appended to typeIndexToTokenMapBlob
sigInOffsetEntries.Add(new KeyValuePair<uint, uint>(typeIndex, sigInOffset));
}
else
{
typeIndexToTokenMapBlob.WriteDWORD(typeIndex);
typeIndexToTokenMapBlob.WriteDWORD(typeDataBlob.Size());
typeDataBlob.WriteBuffer(blobBuilder);
}
}
// sort sigInOffsetEntries based on sigInOffset
sigInOffsetEntries.Sort((KeyValuePair<uint, uint> left, KeyValuePair<uint, uint> right) =>
{
if (left.Value < right.Value)
return -1;
if (left.Value == right.Value)
return 0;
return 1;
});
// write the sorted sigInOffsetEntries
foreach (KeyValuePair<uint, uint> sigInOffsetEntry in sigInOffsetEntries)
{
typeIndexToTokenMapBlob.WriteDWORD(sigInOffsetEntry.Key);
typeIndexToTokenMapBlob.WriteDWORD(sigInOffsetEntry.Value);
}
// add typeDataBlob to the end of m_typeIndexToTokenMapBlob
typeIndexToTokenMapBlob.WriteBuffer(typeDataBlob.ToArray());
return typeIndexToTokenMapBlob;
}
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 });
if (factory.WindowsDebugData.DebugTypeRecordsSection != null)
factory.WindowsDebugData.DebugTypeRecordsSection.Neuter();
DebugInfoBlob debugData = GetDebugTypeIndexToTokenMap(factory.WindowsDebugData.DebugPseudoAssemblySection.PseudoAssembly, factory.WindowsDebugData.UserDefinedTypeDescriptor.CompleteKnownTypes);
return new ObjectData(debugData.ToArray(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
}
protected override string GetName(NodeFactory context)
{
return "___DebugTypeSignatureMapSection";
}
}
}

Просмотреть файл

@ -0,0 +1,527 @@
// 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.Linq;
using System.Reflection;
using System.Collections.Generic;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.Metadata;
using System.Collections.Immutable;
using System.Reflection.PortableExecutable;
using System.IO;
using System.Diagnostics;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
using ILCompiler.DependencyAnalysis;
namespace ILCompiler
{
public class ManagedBinaryEmitter
{
public class EmittedTypeDefinition
{
private readonly ManagedBinaryEmitter _managedEmitter;
private List<EmittedMethodDefinition> _methods = new List<EmittedMethodDefinition>();
public string Name { get; private set; }
public bool IsValueType { get; private set; }
public IReadOnlyList<EmittedMethodDefinition> Methods => _methods;
internal EmittedTypeDefinition(string name, bool isValueType, ManagedBinaryEmitter managedEmitter)
{
Name = name;
IsValueType = isValueType;
_managedEmitter = managedEmitter;
}
public EmittedMethodDefinition EmitMethodDefinition(string name, MethodSignature signature)
{
var newMethodDef = new EmittedMethodDefinition(name, signature, _managedEmitter);
_methods.Add(newMethodDef);
return newMethodDef;
}
}
public class EmittedMethodDefinition
{
private readonly ManagedBinaryEmitter _managedEmitter;
public string Name { get; private set; }
public MethodSignature Signature { get; private set; }
public InstructionEncoder Code { get; private set; }
internal EmittedMethodDefinition(string name, MethodSignature signature, ManagedBinaryEmitter managedEmitter)
{
Name = name;
Signature = signature;
_managedEmitter = managedEmitter;
Code = new InstructionEncoder(new BlobBuilder());
}
}
private readonly TypeSystemContext _typeSystemContext;
private MetadataBuilder _metadataBuilder;
private MethodBodyStreamEncoder _methodBodyStream;
private List<EmittedTypeDefinition> _emittedTypes;
protected MetadataBuilder Builder => _metadataBuilder;
public ManagedBinaryEmitter(TypeSystemContext typeSystemContext, string assemblyName)
{
_typeSystemContext = typeSystemContext;
_metadataBuilder = new MetadataBuilder();
_methodBodyStream = new MethodBodyStreamEncoder(new BlobBuilder());
_emittedTypes = new List<EmittedTypeDefinition>();
_metadataBuilder.AddAssembly(
_metadataBuilder.GetOrAddString(assemblyName),
new Version(0, 0, 0, 0),
culture: default(StringHandle),
publicKey: default(BlobHandle),
flags: default(AssemblyFlags),
hashAlgorithm: AssemblyHashAlgorithm.None);
// Module type
_metadataBuilder.AddTypeDefinition(
default(TypeAttributes),
default(StringHandle),
_metadataBuilder.GetOrAddString("<Module>"),
baseType: default(EntityHandle),
fieldList: MetadataTokens.FieldDefinitionHandle(1),
methodList: MetadataTokens.MethodDefinitionHandle(1));
}
public EmittedTypeDefinition EmitTypeDefinition(string typeName, bool isValueType)
{
EmittedTypeDefinition newTypeDef = new EmittedTypeDefinition(typeName, isValueType, this);
_emittedTypes.Add(newTypeDef);
return newTypeDef;
}
public EntityHandle EmitMetadataHandleForTypeSystemEntity(TypeSystemEntity entity)
{
switch (entity)
{
case FieldDesc field: return MakeMemberReferenceHandle(field);
case MethodDesc method: return MakeMemberReferenceHandle(method);
case TypeDesc type: return MakeTypeRefOrSpecHandle(type);
default:
throw new NotSupportedException();
}
}
public BlobHandle EmitSignatureBlobForMethodSignature(MethodSignature signature)
{
return MakeSignatureHandle(signature);
}
/// <summary>
/// Encode a type signature into a specified blob.
/// </summary>
/// <param name="blobBuilder">Blob to encode type signature into. Must not be null</param>
public void EncodeSignatureForType(TypeDesc type, BlobBuilder blobBuilder)
{
SignatureTypeEncoder sigEncoder = new SignatureTypeEncoder(blobBuilder);
EncodeTypeSignature(sigEncoder, type);
}
public void EmitOutputFile(string outputPath)
{
using (FileStream sw = new FileStream(outputPath, FileMode.Create, FileAccess.ReadWrite))
{
EmitToStream(sw);
}
}
public void EmitToStream(Stream stream)
{
foreach (var typeDef in _emittedTypes)
{
MethodDefinitionHandle? firstMethodHandle = null;
foreach (var methodDef in typeDef.Methods)
{
int bodyOffset = _methodBodyStream.AddMethodBody(methodDef.Code);
BlobHandle signature = MakeSignatureHandle(methodDef.Signature);
MethodDefinitionHandle methodHandle = _metadataBuilder.AddMethodDefinition(
MethodAttributes.PrivateScope | MethodAttributes.Static,
MethodImplAttributes.IL | MethodImplAttributes.Managed,
_metadataBuilder.GetOrAddString(methodDef.Name),
signature,
bodyOffset,
parameterList: default(ParameterHandle));
if (firstMethodHandle == null)
firstMethodHandle = methodHandle;
}
_metadataBuilder.AddTypeDefinition(
default(TypeAttributes),
default(StringHandle),
_metadataBuilder.GetOrAddString(typeDef.Name),
typeDef.IsValueType ?
MakeTypeRefHandle(_typeSystemContext.GetWellKnownType(WellKnownType.ValueType)) :
MakeTypeRefHandle(_typeSystemContext.GetWellKnownType(WellKnownType.Object)),
fieldList: MetadataTokens.FieldDefinitionHandle(1),
methodList: firstMethodHandle.Value);
}
BlobBuilder peBlob = new BlobBuilder();
new ManagedPEBuilder(PEHeaderBuilder.CreateLibraryHeader(), new MetadataRootBuilder(_metadataBuilder), _methodBodyStream.Builder).Serialize(peBlob);
peBlob.WriteContentTo(stream);
// Clear some variables to catch any caller trying to emit data after writing the output file
_emittedTypes = null;
_metadataBuilder = null;
_methodBodyStream = default(MethodBodyStreamEncoder);
}
#region TypeSystem Entities To Handle Encoders
private Dictionary<EcmaAssembly, AssemblyReferenceHandle> _assemblyRefHandles = new Dictionary<EcmaAssembly, AssemblyReferenceHandle>();
private Dictionary<TypeDesc, EntityHandle> _typeRefOrSpecHandles = new Dictionary<TypeDesc, EntityHandle>();
private Dictionary<TypeSystemEntity, EntityHandle> _memberRefOrSpecHandles = new Dictionary<TypeSystemEntity, EntityHandle>();
private Dictionary<MethodSignature, BlobHandle> _methodSignatureHandles = new Dictionary<MethodSignature, BlobHandle>();
private Dictionary<FieldDesc, BlobHandle> _fieldSignatureHandles = new Dictionary<FieldDesc, BlobHandle>();
private void EncodeTypeSignature(SignatureTypeEncoder encoder, TypeDesc type)
{
if (type is RuntimeDeterminedType)
{
EncodeTypeSignature(encoder, ((RuntimeDeterminedType)type).RuntimeDeterminedDetailsType);
return;
}
switch (type.Category)
{
case TypeFlags.Boolean:
encoder.Boolean(); break;
case TypeFlags.Byte:
encoder.Byte(); break;
case TypeFlags.SByte:
encoder.SByte(); break;
case TypeFlags.Char:
encoder.Char(); break;
case TypeFlags.Int16:
encoder.Int16(); break;
case TypeFlags.UInt16:
encoder.UInt16(); break;
case TypeFlags.Int32:
encoder.Int32(); break;
case TypeFlags.UInt32:
encoder.UInt32(); break;
case TypeFlags.Int64:
encoder.Int64(); break;
case TypeFlags.UInt64:
encoder.UInt64(); break;
case TypeFlags.Single:
encoder.Single(); break;
case TypeFlags.Double:
encoder.Double(); break;
case TypeFlags.IntPtr:
encoder.IntPtr(); break;
case TypeFlags.UIntPtr:
encoder.UIntPtr(); break;
case TypeFlags.Void:
encoder.Builder.WriteByte((byte)PrimitiveTypeCode.Void);
break;
case TypeFlags.SignatureTypeVariable:
encoder.GenericTypeParameter(((SignatureVariable)type).Index);
break;
case TypeFlags.SignatureMethodVariable:
encoder.GenericMethodTypeParameter(((SignatureMethodVariable)type).Index);
break;
case TypeFlags.GenericParameter:
{
var genericTypeDesc = (GenericParameterDesc)type;
if (genericTypeDesc.Kind == GenericParameterKind.Type)
encoder.GenericTypeParameter(genericTypeDesc.Index);
else
encoder.GenericMethodTypeParameter(genericTypeDesc.Index);
}
break;
case TypeFlags.FunctionPointer:
{
FunctionPointerType fptrType = (FunctionPointerType)type;
encoder.FunctionPointer(
SignatureCallingConvention.Default,
fptrType.Signature.IsStatic ? default(FunctionPointerAttributes) : FunctionPointerAttributes.HasThis,
fptrType.Signature.GenericParameterCount);
// Return Type Sig
EncodeTypeSignature(encoder, fptrType.Signature.ReturnType);
// Parameter Types Sig
for (int i = 0; i < fptrType.Signature.Length; i++)
EncodeTypeSignature(encoder, fptrType.Signature[i]);
}
break;
case TypeFlags.Array:
{
// Skip bounds and lobounds (TODO)
ImmutableArray<int> bounds = ImmutableArray.Create<int>();
ImmutableArray<int> lowerBounds = ImmutableArray.Create<int>();
encoder.Array(
elementType => EncodeTypeSignature(elementType, ((ArrayType)type).ElementType),
arrayShape => arrayShape.Shape(((ArrayType)type).Rank, bounds, lowerBounds));
}
break;
case TypeFlags.SzArray:
encoder.SZArray();
EncodeTypeSignature(encoder, ((ParameterizedType)type).ParameterType);
break;
case TypeFlags.ByRef:
encoder.Builder.WriteByte((byte)SignatureTypeCode.ByReference);
EncodeTypeSignature(encoder, ((ParameterizedType)type).ParameterType);
break;
case TypeFlags.Pointer:
encoder.Builder.WriteByte((byte)SignatureTypeCode.Pointer);
EncodeTypeSignature(encoder, ((ParameterizedType)type).ParameterType);
break;
case TypeFlags.Enum:
case TypeFlags.Class:
case TypeFlags.ValueType:
case TypeFlags.Interface:
case TypeFlags.Nullable:
{
if (type == _typeSystemContext.GetWellKnownType(WellKnownType.TypedReference))
encoder.Builder.WriteByte((byte)PrimitiveTypeCode.TypedReference);
else if (type == _typeSystemContext.GetWellKnownType(WellKnownType.Object))
encoder.PrimitiveType(PrimitiveTypeCode.Object);
else if (type == _typeSystemContext.GetWellKnownType(WellKnownType.String))
encoder.PrimitiveType(PrimitiveTypeCode.String);
else if (type.HasInstantiation && !type.IsGenericDefinition)
{
encoder.GenericInstantiation(MakeTypeRefOrSpecHandle(type.GetTypeDefinition()), type.Instantiation.Length, type.IsValueType);
for (int i = 0; i < type.Instantiation.Length; i++)
EncodeTypeSignature(encoder, type.Instantiation[i]);
}
else
{
encoder.Type(MakeTypeRefHandle(type), type.IsValueType);
}
}
break;
default:
throw new InvalidOperationException("Attempting to encode an invalid type signature.");
}
}
private BlobHandle MakeSignatureHandle(MethodSignature signature)
{
BlobHandle handle;
if (!_methodSignatureHandles.TryGetValue(signature, out handle))
{
BlobBuilder metadataSignature = new BlobBuilder();
MethodSignatureEncoder methodSigEncoder = new BlobEncoder(metadataSignature).MethodSignature(
SignatureCallingConvention.Default, signature.GenericParameterCount, !signature.IsStatic);
ReturnTypeEncoder returnTypeEncoder;
ParametersEncoder parametersEncoder;
methodSigEncoder.Parameters(signature.Length, out returnTypeEncoder, out parametersEncoder);
// Return Type Sig
EncodeTypeSignature(returnTypeEncoder.Type(), signature.ReturnType);
// Parameter Types Sig
for (int i = 0; i < signature.Length; i++)
EncodeTypeSignature(parametersEncoder.AddParameter().Type(), signature[i]);
_methodSignatureHandles[signature] = handle = _metadataBuilder.GetOrAddBlob(metadataSignature);
}
return handle;
}
private BlobHandle MakeSignatureHandle(TypeSystemEntity methodOrField)
{
if (methodOrField is MethodDesc)
{
return MakeSignatureHandle(((MethodDesc)methodOrField).Signature);
}
else
{
BlobHandle handle;
FieldDesc field = (FieldDesc)methodOrField;
if (!_fieldSignatureHandles.TryGetValue(field, out handle))
{
BlobBuilder metadataSignature = new BlobBuilder();
SignatureTypeEncoder fieldSigEncoder = new BlobEncoder(metadataSignature).FieldSignature();
EncodeTypeSignature(fieldSigEncoder, field.FieldType);
_fieldSignatureHandles[field] = handle = _metadataBuilder.GetOrAddBlob(metadataSignature);
}
return handle;
}
}
private AssemblyReferenceHandle MakeAssemblyReferenceHandle(EcmaAssembly assemblyRef)
{
AssemblyReferenceHandle handle;
if (!_assemblyRefHandles.TryGetValue(assemblyRef, out handle))
{
AssemblyName assemblyName = assemblyRef.GetName();
handle = _metadataBuilder.AddAssemblyReference(
_metadataBuilder.GetOrAddString(assemblyName.Name),
assemblyName.Version,
default(StringHandle),
_metadataBuilder.GetOrAddBlob(ImmutableArray.Create<byte>(assemblyName.GetPublicKeyToken())),
default(AssemblyFlags),
default(BlobHandle));
_assemblyRefHandles[assemblyRef] = handle;
}
return handle;
}
private AssemblyReferenceHandle MakeCorlibAssemblyReferenceHandle()
{
return MakeAssemblyReferenceHandle((EcmaAssembly)_typeSystemContext.SystemModule);
}
private EntityHandle MakeTypeRefHandle(TypeDesc type)
{
Debug.Assert(type.IsTypeDefinition);
Debug.Assert((type is EcmaType) || _typeSystemContext.IsCanonicalDefinitionType(type, CanonicalFormKind.Any));
EntityHandle handle;
if (!_typeRefOrSpecHandles.TryGetValue(type, out handle))
{
if (_typeSystemContext.IsCanonicalDefinitionType(type, CanonicalFormKind.Any))
{
CanonBaseType canonType = (CanonBaseType)type;
handle = _metadataBuilder.AddTypeReference(
MakeCorlibAssemblyReferenceHandle(),
_metadataBuilder.GetOrAddString(canonType.Namespace),
_metadataBuilder.GetOrAddString(canonType.Name));
}
else
{
EntityHandle scope;
EcmaType typeAsEcmaType = (EcmaType)type;
if (typeAsEcmaType.ContainingType != null)
scope = MakeTypeRefHandle(typeAsEcmaType.ContainingType);
else
scope = MakeAssemblyReferenceHandle((EcmaAssembly)typeAsEcmaType.EcmaModule);
handle = _metadataBuilder.AddTypeReference(
scope,
_metadataBuilder.GetOrAddString(typeAsEcmaType.Namespace),
_metadataBuilder.GetOrAddString(typeAsEcmaType.Name));
}
_typeRefOrSpecHandles[type] = handle;
}
return handle;
}
private EntityHandle MakeTypeRefOrSpecHandle(TypeDesc type)
{
EntityHandle handle;
if (!_typeRefOrSpecHandles.TryGetValue(type, out handle))
{
if(!type.IsDefType || !type.IsTypeDefinition || type is RuntimeDeterminedType)
{
SignatureTypeEncoder sigEncoder = new SignatureTypeEncoder(new BlobBuilder());
EncodeTypeSignature(sigEncoder, type);
handle = _metadataBuilder.AddTypeSpecification(_metadataBuilder.GetOrAddBlob(sigEncoder.Builder));
}
else
{
handle = MakeTypeRefHandle(type);
}
_typeRefOrSpecHandles[type] = handle;
}
return handle;
}
private EntityHandle MakeMemberReferenceHandle(TypeSystemEntity methodOrField)
{
EntityHandle handle;
if (!_memberRefOrSpecHandles.TryGetValue(methodOrField, out handle))
{
MethodDesc method = methodOrField as MethodDesc;
FieldDesc field = methodOrField as FieldDesc;
TypeDesc owningType = (method != null ? method.OwningType : field.OwningType);
string name = (method != null ? method.Name : field.Name);
BlobHandle signature = method != null ?
MakeSignatureHandle(method.GetTypicalMethodDefinition()) :
MakeSignatureHandle(field);
handle = _metadataBuilder.AddMemberReference(
MakeTypeRefOrSpecHandle(owningType),
_metadataBuilder.GetOrAddString(name),
signature);
if (method != null && method.HasInstantiation && !method.IsTypicalMethodDefinition)
{
BlobEncoder methodSpecEncoder = new BlobEncoder(new BlobBuilder());
GenericTypeArgumentsEncoder argEncoder = methodSpecEncoder.MethodSpecificationSignature(method.Instantiation.Length);
for (int i = 0; i < method.Instantiation.Length; i++)
{
SignatureTypeEncoder argTypeEncoder = argEncoder.AddArgument();
EncodeTypeSignature(argTypeEncoder, method.Instantiation[i]);
}
handle = _metadataBuilder.AddMethodSpecification(handle, _metadataBuilder.GetOrAddBlob(methodSpecEncoder.Builder));
}
_memberRefOrSpecHandles[methodOrField] = handle;
}
return handle;
}
#endregion
}
public static class InstructionEncoderExtensions
{
public static void EmitLdToken(this InstructionEncoder code, TypeSystemEntity typeSystemEntity, ManagedBinaryEmitter emitter)
{
code.OpCode(ILOpCode.Ldtoken);
code.Token(emitter.EmitMetadataHandleForTypeSystemEntity(typeSystemEntity));
}
public static void EmitI4Constant(this InstructionEncoder code, int value)
{
code.OpCode(ILOpCode.Ldc_i4);
code.CodeBuilder.WriteInt32(value);
}
}
}

Просмотреть файл

@ -0,0 +1,94 @@
// 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.Diagnostics;
using System.Text;
using System.IO;
using System.Reflection;
using Internal.TypeSystem.Ecma;
using Internal.TypeSystem.TypesDebugInfo;
namespace ILCompiler
{
public class MergedAssemblyRecord
{
public EcmaAssembly Assembly { get; }
public string Name { get; }
public uint AssemblyIndex { get; }
public uint Timestamp { get; }
public bool HasPDB { get; }
public byte[] PublicKey { get; }
public byte[] VersionInfo { get; }
public int VersionInfoLength
{
get
{
return BitConverter.ToUInt16(VersionInfo, 0);
}
}
public MergedAssemblyRecord(EcmaAssembly assembly, string name, uint assemblyIndex, uint timestamp, bool hasPDB, byte[] publicKey, byte[] versionInfo)
{
Assembly = assembly;
Name = name;
AssemblyIndex = assemblyIndex;
Timestamp = timestamp;
HasPDB = hasPDB;
PublicKey = publicKey;
VersionInfo = versionInfo;
if (versionInfo.Length < sizeof(ushort))
throw new ArgumentException("versionInfo");
int versionInfoLength = VersionInfoLength;
if (versionInfoLength == 0)
{
VersionInfo = BitConverter.GetBytes((ushort)sizeof(ushort));
Debug.Assert(VersionInfoLength == sizeof(ushort));
}
else
{
// Validate that a non-empty version info contains a VS_VERSION_INFO structure
string vsVersionInfoString = "VS_VERSION_INFO";
if (VersionInfoLength < (6 + vsVersionInfoString.Length * sizeof(char)))
throw new ArgumentException("versionInfo");
string encodedString = Encoding.Unicode.GetString(versionInfo, 6, vsVersionInfoString.Length * sizeof(char));
if (encodedString != vsVersionInfoString)
throw new ArgumentException("versionInfo");
}
}
internal void Encode(DebugInfoBlob blob)
{
blob.WriteDWORD(Timestamp);
blob.WriteDWORD(AssemblyIndex & 0x7FFFFFFF | (HasPDB ? 0x80000000 : 0));
blob.WriteBuffer(VersionInfo, 0, VersionInfoLength);
string nameWithPublicKey = Name;
if (PublicKey != null && PublicKey.Length > 0)
{
nameWithPublicKey += ", PublicKey=";
nameWithPublicKey += BitConverter.ToString(PublicKey).Replace("-", "");
}
blob.WriteString(nameWithPublicKey);
blob.AlignToDWORD();
}
}
public class MergedAssemblyRecords
{
public IReadOnlyCollection<MergedAssemblyRecord> MergedAssemblies { get; }
public MergedAssemblyRecords(IReadOnlyCollection<MergedAssemblyRecord> mergedAssemblies)
{
MergedAssemblies = mergedAssemblies;
}
}
}

Просмотреть файл

@ -42,6 +42,7 @@ namespace ILCompiler
private HashSet<TypeDesc> _typesWithConstructedEETypesGenerated = new HashSet<TypeDesc>();
private HashSet<MethodDesc> _methodsGenerated = new HashSet<MethodDesc>();
private HashSet<GenericDictionaryNode> _genericDictionariesGenerated = new HashSet<GenericDictionaryNode>();
private HashSet<IMethodBodyNode> _methodBodiesGenerated = new HashSet<IMethodBodyNode>();
private List<ModuleDesc> _modulesWithMetadata = new List<ModuleDesc>();
private List<TypeGVMEntriesNode> _typeGVMEntries = new List<TypeGVMEntriesNode>();
@ -155,6 +156,12 @@ namespace ILCompiler
return;
}
IMethodBodyNode methodBodyNode = obj as IMethodBodyNode;
if (methodBodyNode != null)
{
_methodBodiesGenerated.Add(methodBodyNode);
}
IMethodNode methodNode = obj as MethodCodeNode;
if (methodNode == null)
methodNode = obj as ShadowConcreteMethodNode;
@ -548,7 +555,7 @@ namespace ILCompiler
return _typeGVMEntries;
}
internal IEnumerable<GenericDictionaryNode> GetCompiledGenericDictionaries()
internal IReadOnlyCollection<GenericDictionaryNode> GetCompiledGenericDictionaries()
{
return _genericDictionariesGenerated;
}
@ -558,6 +565,11 @@ namespace ILCompiler
return _methodsGenerated;
}
internal IEnumerable<IMethodBodyNode> GetCompiledMethodBodies()
{
return _methodBodiesGenerated;
}
internal bool TypeGeneratesEEType(TypeDesc type)
{
return _typesWithEETypesGenerated.Contains(type);

Просмотреть файл

@ -410,6 +410,17 @@ namespace ILCompiler
return MetadataCategory.RuntimeMapping;
}
private bool IsMethodSupportedInPrecomputedReflection(MethodDesc method)
{
if (!IsMethodSupportedInReflectionInvoke(method))
return false;
MethodDesc typicalInvokeTarget = method.GetTypicalMethodDefinition();
MethodDesc typicalDynamicInvokeStub;
return _dynamicInvokeStubs.Value.TryGetValue(typicalInvokeTarget, out typicalDynamicInvokeStub);
}
void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider)
{
MetadataLoadedInfo loadedMetadata = _loadedMetadata.Value;
@ -421,6 +432,9 @@ namespace ILCompiler
if (method.HasInstantiation || method.OwningType.HasInstantiation)
continue;
if (!IsMethodSupportedInPrecomputedReflection(method))
continue;
if (method.IsVirtual)
rootProvider.RootVirtualMethodForReflection(method, "Reflection root");
else
@ -438,6 +452,9 @@ namespace ILCompiler
// Virtual methods need special handling (e.g. with dependency tracking) since they can be abstract.
foreach (var method in loadedMetadata.RequiredGenericMethods)
{
if (!IsMethodSupportedInPrecomputedReflection(method))
continue;
if (method.IsVirtual)
rootProvider.RootVirtualMethodForReflection(method, "Required generic method");
else

Просмотреть файл

@ -1,4 +1,4 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" Condition="'$(IsProjectNLibrary)' != 'true'" />
<PropertyGroup>
<OutputType>Library</OutputType>
@ -95,10 +95,20 @@
<Compile Include="Compiler\CompilerTypeSystemContext.Mangling.cs" />
<Compile Include="Compiler\CompilerTypeSystemContext.Sorting.cs" />
<Compile Include="Compiler\CompilerGeneratedInteropStubManager .cs" />
<Compile Include="Compiler\DependencyAnalysis\WindowsDebugILImagesSection.cs" />
<Compile Include="Compiler\DependencyAnalysis\WindowsDebugManagedNativeDictionaryInfoSection.cs" />
<Compile Include="Compiler\DependencyAnalysis\WindowsDebugMergedAssemblyRecordsSection.cs" />
<Compile Include="Compiler\DependencyAnalysis\WindowsDebugMethodMapSection.cs" />
<Compile Include="Compiler\DependencyAnalysis\WindowsDebugNeedTypeIndicesStoreNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\WindowsDebugPseudoAssemblySection.cs" />
<Compile Include="Compiler\DependencyAnalysis\WindowsDebugTypeRecordsSection.cs" />
<Compile Include="Compiler\DependencyAnalysis\WindowsDebugTypeSignatureMapSection.cs" />
<Compile Include="Compiler\DependencyAnalysis\CustomAttributeBasedDependencyAlgorithm.cs" />
<Compile Include="Compiler\DependencyAnalysis\FieldMetadataNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ILScanNodeFactory.cs" />
<Compile Include="Compiler\DependencyAnalysis\IMethodBodyNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\IMethodBodyNodeWithFuncletSymbols.cs" />
<Compile Include="Compiler\DependencyAnalysis\ISymbolNodeWithFuncletId.cs" />
<Compile Include="Compiler\DependencyAnalysis\LoopHijackFlagNode.cs" />
<Compile Include="Compiler\DictionaryLayoutProvider.cs" />
<Compile Include="Compiler\EmptyInteropStubManager.cs" />
@ -222,6 +232,7 @@
<Compile Include="Compiler\DependencyAnalysis\NodeFactory.cs" />
<Compile Include="Compiler\DependencyAnalysis\NodeFactory.GenericLookups.cs" />
<Compile Include="Compiler\DependencyAnalysis\NodeFactory.NativeLayout.cs" />
<Compile Include="Compiler\DependencyAnalysis\NodeFactory.WindowsDebugData.cs" />
<Compile Include="Compiler\DependencyAnalysis\NonGCStaticsNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ObjectAndOffsetSymbolNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ObjectDataBuilder.cs" />
@ -269,8 +280,10 @@
<Compile Include="Compiler\LazyGenericsPolicy.cs" />
<Compile Include="Compiler\LibraryRootProvider.cs" />
<Compile Include="Compiler\MainMethodRootProvider.cs" />
<Compile Include="Compiler\ManagedBinaryEmitter.cs" />
<Compile Include="Compiler\MemoryHelper.cs" />
<Compile Include="Compiler\CompilerGeneratedMetadataManager.cs" />
<Compile Include="Compiler\MergedAssemblyRecords.cs" />
<Compile Include="Compiler\MetadataManager.cs" />
<Compile Include="Compiler\InteropStubManager.cs" />
<Compile Include="Compiler\MethodExtensions.cs" />
@ -356,6 +369,9 @@
<Compile Include="..\..\Common\src\TypeSystem\TypesDebugInfoWriter\TypesDebugInfoWriter.cs">
<Link>TypeSystem\TypesDebugInfoWriter\TypesDebugInfoWriter.cs</Link>
</Compile>
<Compile Include="..\..\Common\src\TypeSystem\TypesDebugInfoWriter\DebugInfoWriter.cs">
<Link>TypeSystem\TypesDebugInfoWriter\DebugInfoWriter.cs</Link>
</Compile>
<Compile Include="..\..\Common\src\TypeSystem\TypesDebugInfoWriter\UserDefinedTypeDescriptor.cs">
<Link>TypeSystem\TypesDebugInfoWriter\UserDefinedTypeDescriptor.cs</Link>
</Compile>

Просмотреть файл

@ -241,6 +241,15 @@ typedef DPTR(uint32_t) PTR_uint32_t;
enum CLRDataEnumMemoryFlags : int;
enum ThreadType
{
ThreadType_GC = 137,
};
#undef ClrFlsSetThreadType
#define ClrFlsSetThreadType(threadType) SetGCSpecialThread(threadType)
void SetGCSpecialThread(ThreadType threadType);
#if defined(ENABLE_PERF_COUNTERS) || defined(FEATURE_EVENT_TRACE)
// Note this is not updated in a thread safe way so the value may not be accurate. We get
// it accurately in full GCs if the handle count is requested.

Просмотреть файл

@ -1259,11 +1259,13 @@ gc_alloc_context * Thread::GetAllocContext()
return dac_cast<DPTR(gc_alloc_context)>(dac_cast<TADDR>(this) + offsetof(Thread, m_rgbAllocContextBuffer));
}
#ifndef DACCESS_COMPILE
bool IsGCSpecialThread()
{
// TODO: Implement for background GC
return false;
return ThreadStore::GetCurrentThread()->IsGCSpecial();
}
#endif // DACCESS_COMPILE
GPTR_IMPL(Thread, g_pFinalizerThread);
GPTR_IMPL(Thread, g_pGcThread);
@ -1280,15 +1282,23 @@ bool __SwitchToThread(uint32_t dwSleepMSec, uint32_t /*dwSwitchCount*/)
return !!PalSwitchToThread();
}
void SetGCSpecialThread(ThreadType threadType)
{
Thread *pThread = ThreadStore::RawGetCurrentThread();
pThread->SetGCSpecial(threadType == ThreadType_GC);
}
#endif // DACCESS_COMPILE
MethodTable * g_pFreeObjectMethodTable;
int32_t g_TrapReturningThreads;
#ifndef DACCESS_COMPILE
bool IsGCThread()
{
return false;
return IsGCSpecialThread() || ThreadStore::GetSuspendingThread() == ThreadStore::GetCurrentThread();
}
#endif // DACCESS_COMPILE
void LogSpewAlways(const char * /*fmt*/, ...)
{

Просмотреть файл

@ -334,6 +334,8 @@ bool Thread::IsInitialized()
//
void Thread::SetGCSpecial(bool isGCSpecial)
{
if (!IsInitialized())
Construct();
if (isGCSpecial)
SetState(TSF_IsGcSpecialThread);
else

Просмотреть файл

@ -209,9 +209,9 @@ namespace Internal.Runtime.Augments
//
// Helper to extract the artifact that uniquely identifies a method in the runtime mapping tables.
//
public static IntPtr GetDelegateLdFtnResult(Delegate d, out RuntimeTypeHandle typeOfFirstParameterIfInstanceDelegate, out bool isOpenResolver)
public static IntPtr GetDelegateLdFtnResult(Delegate d, out RuntimeTypeHandle typeOfFirstParameterIfInstanceDelegate, out bool isOpenResolver, out bool isInterpreterEntrypoint)
{
return d.GetFunctionPointer(out typeOfFirstParameterIfInstanceDelegate, out isOpenResolver);
return d.GetFunctionPointer(out typeOfFirstParameterIfInstanceDelegate, out isOpenResolver, out isInterpreterEntrypoint);
}
public static void GetDelegateData(Delegate delegateObj, out object firstParameter, out object helperObject, out IntPtr extraFunctionPointerOrData, out IntPtr functionPointer)
@ -277,6 +277,11 @@ namespace Internal.Runtime.Augments
return RuntimeImports.RhBox(fieldType.ToEETypePtr(), *(void**)&address);
}
public static unsafe object LoadPointerTypeField(IntPtr address, RuntimeTypeHandle fieldType)
{
return Pointer.Box(*(void**)address, Type.GetTypeFromHandle(fieldType));
}
public static unsafe void StoreValueTypeField(ref byte address, Object fieldValue, RuntimeTypeHandle fieldType)
{
RuntimeImports.RhUnbox(fieldValue, ref address, fieldType.ToEETypePtr());
@ -302,6 +307,16 @@ namespace Internal.Runtime.Augments
}
}
public static unsafe Object LoadPointerTypeField(Object obj, int fieldOffset, RuntimeTypeHandle fieldType)
{
fixed (IntPtr* pObj = &obj.m_pEEType)
{
IntPtr pData = (IntPtr)pObj;
IntPtr pField = pData + fieldOffset;
return LoadPointerTypeField(pField, fieldType);
}
}
public static unsafe void StoreReferenceTypeField(IntPtr address, Object fieldValue)
{
Volatile.Write<Object>(ref Unsafe.As<IntPtr, Object>(ref *(IntPtr*)address), fieldValue);
@ -365,6 +380,19 @@ namespace Internal.Runtime.Augments
return Unsafe.As<byte, object>(ref Unsafe.Add<byte>(ref typedReference.Value, fieldOffset));
}
[CLSCompliant(false)]
public static object LoadPointerTypeFieldValueFromValueType(TypedReference typedReference, int fieldOffset, RuntimeTypeHandle fieldTypeHandle)
{
Debug.Assert(TypedReference.TargetTypeToken(typedReference).ToEETypePtr().IsValueType);
Debug.Assert(fieldTypeHandle.ToEETypePtr().IsPointer);
IntPtr ptrValue = Unsafe.As<byte, IntPtr>(ref Unsafe.Add<byte>(ref typedReference.Value, fieldOffset));
unsafe
{
return Pointer.Box((void*)ptrValue, Type.GetTypeFromHandle(fieldTypeHandle));
}
}
public static unsafe int ObjectHeaderSize => sizeof(EETypePtr);
[DebuggerGuidedStepThroughAttribute]
@ -732,9 +760,7 @@ namespace Internal.Runtime.Augments
public static String TryGetFullPathToMainApplication()
{
Func<String> delegateToAnythingInsideMergedApp = TryGetFullPathToMainApplication;
RuntimeTypeHandle thDummy;
bool boolDummy;
IntPtr ipToAnywhereInsideMergedApp = delegateToAnythingInsideMergedApp.GetFunctionPointer(out thDummy, out boolDummy);
IntPtr ipToAnywhereInsideMergedApp = delegateToAnythingInsideMergedApp.GetFunctionPointer(out RuntimeTypeHandle _, out bool __, out bool ___);
IntPtr moduleBase = RuntimeImports.RhGetOSModuleFromPointer(ipToAnywhereInsideMergedApp);
return TryGetFullPathToApplicationModule(moduleBase);
}

Просмотреть файл

@ -109,16 +109,26 @@ namespace System
/// <param name="isOpenResolver">
/// This value indicates if the returned pointer is an open resolver structure.
/// </param>
/// <param name="isInterpreterEntrypoint">
/// Delegate points to an object array thunk (the delegate wraps a Func<object[], object> delegate). This
/// is typically a delegate pointing to the LINQ expression interpreter.
/// </param>
/// <returns></returns>
unsafe internal IntPtr GetFunctionPointer(out RuntimeTypeHandle typeOfFirstParameterIfInstanceDelegate, out bool isOpenResolver)
unsafe internal IntPtr GetFunctionPointer(out RuntimeTypeHandle typeOfFirstParameterIfInstanceDelegate, out bool isOpenResolver, out bool isInterpreterEntrypoint)
{
typeOfFirstParameterIfInstanceDelegate = default(RuntimeTypeHandle);
isOpenResolver = false;
isInterpreterEntrypoint = false;
if (GetThunk(MulticastThunk) == m_functionPointer)
{
return IntPtr.Zero;
}
else if (GetThunk(ObjectArrayThunk) == m_functionPointer)
{
isInterpreterEntrypoint = true;
return IntPtr.Zero;
}
else if (m_extraFunctionPointerOrData != IntPtr.Zero)
{
if (GetThunk(OpenInstanceThunk) == m_functionPointer)
@ -899,8 +909,7 @@ namespace System
else
{
RuntimeTypeHandle typeOfFirstParameterIfInstanceDelegate;
bool isOpenThunk;
IntPtr functionPointer = GetFunctionPointer(out typeOfFirstParameterIfInstanceDelegate, out isOpenThunk);
IntPtr functionPointer = GetFunctionPointer(out typeOfFirstParameterIfInstanceDelegate, out bool __, out bool ___);
if (!FunctionPointerOps.IsGenericMethodPointer(functionPointer))
{
return DebuggerFunctionPointerFormattingHook(functionPointer, typeOfFirstParameterIfInstanceDelegate);

Просмотреть файл

@ -97,8 +97,7 @@ namespace System.Runtime.InteropServices
}
public static IntPtr GetFunctionPointer(this Delegate del, out RuntimeTypeHandle typeOfFirstParameterIfInstanceDelegate)
{
bool dummyIsOpenInstanceFunction;
return del.GetFunctionPointer(out typeOfFirstParameterIfInstanceDelegate, out dummyIsOpenInstanceFunction);
return del.GetFunctionPointer(out typeOfFirstParameterIfInstanceDelegate, out bool _, out bool __);
}
//
@ -112,10 +111,9 @@ namespace System.Runtime.InteropServices
if (!del.IsOpenStatic)
return IntPtr.Zero;
bool dummyIsOpenInstanceFunction;
RuntimeTypeHandle typeOfFirstParameterIfInstanceDelegate;
IntPtr funcPtr = del.GetFunctionPointer(out typeOfFirstParameterIfInstanceDelegate, out dummyIsOpenInstanceFunction);
IntPtr funcPtr = del.GetFunctionPointer(out typeOfFirstParameterIfInstanceDelegate, out bool _, out bool __);
// if the function pointer points to a jump stub return the target
return RuntimeImports.RhGetJmpStubCodeTarget(funcPtr);

Просмотреть файл

@ -17,6 +17,8 @@ using Internal.Runtime.TypeLoader;
using Internal.TypeSystem;
using Internal.Runtime.DebuggerSupport;
using IRC=Internal.Runtime.CallConverter;
namespace Internal.Runtime.DebuggerSupport
{
[McgIntrinsics]
@ -31,6 +33,7 @@ namespace Internal.Runtime.DebuggerSupport
private struct InvokeFunctionData
{
public object thisObj;
public IRC.CallingConvention callingConvention;
public RuntimeTypeHandle[] types;
public byte[][] parameterValues;
public FuncEvalResult result;
@ -219,6 +222,7 @@ namespace Internal.Runtime.DebuggerSupport
);
invokeFunctionData.types = new RuntimeTypeHandle[parameters.Length];
invokeFunctionData.callingConvention = hasThis ? IRC.CallingConvention.ManagedInstance : IRC.CallingConvention.ManagedStatic;
for (int i = 0; i < invokeFunctionData.types.Length; i++)
{
@ -365,8 +369,7 @@ namespace Internal.Runtime.DebuggerSupport
returnAndArgumentTypes[i] = new LocalVariableType(invokeFunctionData.types[i], false, false);
}
// Hard coding static here
DynamicCallSignature dynamicCallSignature = new DynamicCallSignature(Internal.Runtime.CallConverter.CallingConvention.ManagedStatic, returnAndArgumentTypes, returnAndArgumentTypes.Length);
DynamicCallSignature dynamicCallSignature = new DynamicCallSignature(invokeFunctionData.callingConvention, returnAndArgumentTypes, returnAndArgumentTypes.Length);
// Invoke the target method
Exception ex = null;

Просмотреть файл

@ -1315,8 +1315,11 @@ namespace Internal.Reflection.Execution
return RuntimeAugments.IsValueType(fieldTypeHandle) ?
(FieldAccessor)new ValueTypeFieldAccessorForInstanceFields(
fieldAccessMetadata.Offset + fieldOffsetDelta, declaringTypeHandle, fieldTypeHandle) :
(FieldAccessor)new ReferenceTypeFieldAccessorForInstanceFields(
fieldAccessMetadata.Offset + fieldOffsetDelta, declaringTypeHandle, fieldTypeHandle);
RuntimeAugments.IsUnmanagedPointerType(fieldTypeHandle) ?
(FieldAccessor)new PointerTypeFieldAccessorForInstanceFields(
fieldAccessMetadata.Offset + fieldOffsetDelta, declaringTypeHandle, fieldTypeHandle) :
(FieldAccessor)new ReferenceTypeFieldAccessorForInstanceFields(
fieldAccessMetadata.Offset + fieldOffsetDelta, declaringTypeHandle, fieldTypeHandle);
}
case FieldTableFlags.Static:
@ -1363,7 +1366,9 @@ namespace Internal.Reflection.Execution
return RuntimeAugments.IsValueType(fieldTypeHandle) ?
(FieldAccessor)new ValueTypeFieldAccessorForStaticFields(cctorContext, staticsBase, fieldOffset, isGcStatic, fieldTypeHandle) :
(FieldAccessor)new ReferenceTypeFieldAccessorForStaticFields(cctorContext, staticsBase, fieldOffset, isGcStatic, fieldTypeHandle);
RuntimeAugments.IsUnmanagedPointerType(fieldTypeHandle) ?
(FieldAccessor)new PointerTypeFieldAccessorForStaticFields(cctorContext, staticsBase, fieldOffset, isGcStatic, fieldTypeHandle) :
(FieldAccessor)new ReferenceTypeFieldAccessorForStaticFields(cctorContext, staticsBase, fieldOffset, isGcStatic, fieldTypeHandle);
}
case FieldTableFlags.ThreadStatic:
@ -1375,12 +1380,19 @@ namespace Internal.Reflection.Execution
(int)fieldAccessMetadata.Cookie,
fieldAccessMetadata.Offset,
fieldTypeHandle) :
(FieldAccessor)new ReferenceTypeFieldAccessorForThreadStaticFields(
TryGetStaticClassConstructionContext(declaringTypeHandle),
declaringTypeHandle,
(int)fieldAccessMetadata.Cookie,
fieldAccessMetadata.Offset,
fieldTypeHandle);
RuntimeAugments.IsUnmanagedPointerType(fieldTypeHandle) ?
(FieldAccessor)new PointerTypeFieldAccessorForThreadStaticFields(
TryGetStaticClassConstructionContext(declaringTypeHandle),
declaringTypeHandle,
(int)fieldAccessMetadata.Cookie,
fieldAccessMetadata.Offset,
fieldTypeHandle) :
(FieldAccessor)new ReferenceTypeFieldAccessorForThreadStaticFields(
TryGetStaticClassConstructionContext(declaringTypeHandle),
declaringTypeHandle,
(int)fieldAccessMetadata.Cookie,
fieldAccessMetadata.Offset,
fieldTypeHandle);
}
}

Просмотреть файл

@ -2,24 +2,21 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using global::System;
using global::System.Threading;
using global::System.Reflection;
using global::System.Diagnostics;
using global::System.Collections.Generic;
using System;
using System.Reflection;
using global::Internal.Runtime.Augments;
using global::Internal.Reflection.Execution;
using global::Internal.Reflection.Core.Execution;
using Internal.Runtime.Augments;
using Internal.Reflection.Core.Execution;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal abstract class InstanceFieldAccessor : FieldAccessor
{
public InstanceFieldAccessor(RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle)
public InstanceFieldAccessor(RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle, int offsetPlusHeader)
{
this.DeclaringTypeHandle = declaringTypeHandle;
this.FieldTypeHandle = fieldTypeHandle;
this.OffsetPlusHeader = offsetPlusHeader;
}
public abstract override int Offset { get; }
@ -97,7 +94,8 @@ namespace Internal.Reflection.Execution.FieldAccessors
protected abstract Object UncheckedGetField(Object obj);
protected abstract void UncheckedSetField(Object obj, Object value);
protected RuntimeTypeHandle DeclaringTypeHandle { get; private set; }
protected RuntimeTypeHandle FieldTypeHandle { get; private set; }
protected int OffsetPlusHeader { get; }
protected RuntimeTypeHandle DeclaringTypeHandle { get; }
protected RuntimeTypeHandle FieldTypeHandle { get; }
}
}

Просмотреть файл

@ -4,7 +4,6 @@
using System;
using System.Reflection;
using System.Diagnostics;
namespace Internal.Reflection.Execution.FieldAccessors
{

Просмотреть файл

@ -0,0 +1,39 @@
// 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 Internal.Runtime.Augments;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal sealed class PointerTypeFieldAccessorForInstanceFields : InstanceFieldAccessor
{
public PointerTypeFieldAccessorForInstanceFields(int offsetPlusHeader, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle)
: base(declaringTypeHandle, fieldTypeHandle, offsetPlusHeader)
{
}
public sealed override int Offset => OffsetPlusHeader - RuntimeAugments.ObjectHeaderSize;
protected sealed override Object UncheckedGetField(Object obj)
{
return RuntimeAugments.LoadPointerTypeField(obj, OffsetPlusHeader, this.FieldTypeHandle);
}
protected sealed override object UncheckedGetFieldDirectFromValueType(TypedReference typedReference)
{
return RuntimeAugments.LoadPointerTypeFieldValueFromValueType(typedReference, this.Offset, this.FieldTypeHandle);
}
protected sealed override void UncheckedSetField(Object obj, Object value)
{
RuntimeAugments.StoreValueTypeField(obj, OffsetPlusHeader, value, typeof(IntPtr).TypeHandle);
}
protected sealed override void UncheckedSetFieldDirectIntoValueType(TypedReference typedReference, object value)
{
RuntimeAugments.StoreValueTypeFieldValueIntoValueType(typedReference, this.Offset, value, typeof(IntPtr).TypeHandle);
}
}
}

Просмотреть файл

@ -0,0 +1,47 @@
// 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 Internal.Runtime.Augments;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal sealed class PointerTypeFieldAccessorForStaticFields : RegularStaticFieldAccessor
{
public PointerTypeFieldAccessorForStaticFields(IntPtr cctorContext, IntPtr staticsBase, int fieldOffset, bool isGcStatic, RuntimeTypeHandle fieldTypeHandle)
: base(cctorContext, staticsBase, fieldOffset, isGcStatic, fieldTypeHandle)
{
}
unsafe protected sealed override Object GetFieldBypassCctor()
{
#if CORERT
if (IsGcStatic)
{
// The _staticsBase variable points to a GC handle, which points at the GC statics base of the type.
// We need to perform a double indirection in a GC-safe manner.
object gcStaticsRegion = RuntimeAugments.LoadReferenceTypeField(*(IntPtr*)StaticsBase);
return RuntimeAugments.LoadPointerTypeField(gcStaticsRegion, FieldOffset, FieldTypeHandle);
}
#endif
return RuntimeAugments.LoadPointerTypeField(StaticsBase + FieldOffset, FieldTypeHandle);
}
unsafe protected sealed override void UncheckedSetFieldBypassCctor(Object value)
{
#if CORERT
if (IsGcStatic)
{
// The _staticsBase variable points to a GC handle, which points at the GC statics base of the type.
// We need to perform a double indirection in a GC-safe manner.
object gcStaticsRegion = RuntimeAugments.LoadReferenceTypeField(*(IntPtr*)StaticsBase);
RuntimeAugments.StoreValueTypeField(gcStaticsRegion, FieldOffset, value, typeof(IntPtr).TypeHandle);
return;
}
#endif
RuntimeAugments.StoreValueTypeField(StaticsBase + FieldOffset, value, typeof(IntPtr).TypeHandle);
}
}
}

Просмотреть файл

@ -0,0 +1,29 @@
// 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 Internal.Runtime.Augments;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal sealed class PointerTypeFieldAccessorForThreadStaticFields : ThreadStaticFieldAccessor
{
public PointerTypeFieldAccessorForThreadStaticFields(IntPtr cctorContext, RuntimeTypeHandle declaringTypeHandle, int threadStaticsBlockOffset, int fieldOffset, RuntimeTypeHandle fieldTypeHandle)
: base(cctorContext, declaringTypeHandle, threadStaticsBlockOffset, fieldOffset, fieldTypeHandle)
{
}
protected sealed override Object GetFieldBypassCctor()
{
IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(DeclaringTypeHandle, ThreadStaticsBlockOffset, FieldOffset);
return RuntimeAugments.LoadPointerTypeField(fieldAddress, FieldTypeHandle);
}
protected sealed override void UncheckedSetFieldBypassCctor(Object value)
{
IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(DeclaringTypeHandle, ThreadStaticsBlockOffset, FieldOffset);
RuntimeAugments.StoreValueTypeField(fieldAddress, value, typeof(IntPtr).TypeHandle);
}
}
}

Просмотреть файл

@ -2,33 +2,23 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using global::System;
using global::System.Threading;
using global::System.Reflection;
using global::System.Diagnostics;
using global::System.Collections.Generic;
using global::Internal.Runtime.Augments;
using global::Internal.Reflection.Execution;
using global::Internal.Reflection.Core.Execution;
using System;
using Internal.Runtime.Augments;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal sealed class ReferenceTypeFieldAccessorForInstanceFields : InstanceFieldAccessor
{
private int _offset;
public ReferenceTypeFieldAccessorForInstanceFields(int offset, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle)
: base(declaringTypeHandle, fieldTypeHandle)
public ReferenceTypeFieldAccessorForInstanceFields(int offsetPlusHeader, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle)
: base(declaringTypeHandle, fieldTypeHandle, offsetPlusHeader)
{
_offset = offset;
}
public sealed override int Offset => _offset - RuntimeAugments.ObjectHeaderSize;
public sealed override int Offset => OffsetPlusHeader - RuntimeAugments.ObjectHeaderSize;
protected sealed override Object UncheckedGetField(Object obj)
{
return RuntimeAugments.LoadReferenceTypeField(obj, _offset);
return RuntimeAugments.LoadReferenceTypeField(obj, OffsetPlusHeader);
}
protected sealed override object UncheckedGetFieldDirectFromValueType(TypedReference typedReference)
@ -38,7 +28,7 @@ namespace Internal.Reflection.Execution.FieldAccessors
protected sealed override void UncheckedSetField(Object obj, Object value)
{
RuntimeAugments.StoreReferenceTypeField(obj, _offset, value);
RuntimeAugments.StoreReferenceTypeField(obj, OffsetPlusHeader, value);
}
protected sealed override void UncheckedSetFieldDirectIntoValueType(TypedReference typedReference, object value)

Просмотреть файл

@ -2,57 +2,46 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using global::System;
using global::System.Reflection;
using global::System.Runtime.CompilerServices;
using global::System.Runtime.InteropServices;
using global::Internal.Runtime.Augments;
using System;
using Internal.Runtime.Augments;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal sealed class ReferenceTypeFieldAccessorForStaticFields : WritableStaticFieldAccessor
internal sealed class ReferenceTypeFieldAccessorForStaticFields : RegularStaticFieldAccessor
{
private IntPtr _staticsBase;
private bool _isGcStaticsBase;
private int _fieldOffset;
public ReferenceTypeFieldAccessorForStaticFields(IntPtr cctorContext, IntPtr staticsBase, int fieldOffset, bool isGcStatic, RuntimeTypeHandle fieldTypeHandle)
: base(cctorContext, fieldTypeHandle)
: base(cctorContext, staticsBase, fieldOffset, isGcStatic, fieldTypeHandle)
{
_staticsBase = staticsBase;
_isGcStaticsBase = isGcStatic;
_fieldOffset = fieldOffset;
}
unsafe protected sealed override Object GetFieldBypassCctor()
{
#if CORERT
if (_isGcStaticsBase)
if (IsGcStatic)
{
// The _staticsBase variable points to a GC handle, which points at the GC statics base of the type.
// We need to perform a double indirection in a GC-safe manner.
object gcStaticsRegion = RuntimeAugments.LoadReferenceTypeField(*(IntPtr*)_staticsBase);
return RuntimeAugments.LoadReferenceTypeField(gcStaticsRegion, _fieldOffset);
object gcStaticsRegion = RuntimeAugments.LoadReferenceTypeField(*(IntPtr*)StaticsBase);
return RuntimeAugments.LoadReferenceTypeField(gcStaticsRegion, FieldOffset);
}
#endif
return RuntimeAugments.LoadReferenceTypeField(_staticsBase + _fieldOffset);
return RuntimeAugments.LoadReferenceTypeField(StaticsBase + FieldOffset);
}
unsafe protected sealed override void UncheckedSetFieldBypassCctor(Object value)
{
#if CORERT
if (_isGcStaticsBase)
if (IsGcStatic)
{
// The _staticsBase variable points to a GC handle, which points at the GC statics base of the type.
// We need to perform a double indirection in a GC-safe manner.
object gcStaticsRegion = RuntimeAugments.LoadReferenceTypeField(*(IntPtr*)_staticsBase);
RuntimeAugments.StoreReferenceTypeField(gcStaticsRegion, _fieldOffset, value);
object gcStaticsRegion = RuntimeAugments.LoadReferenceTypeField(*(IntPtr*)StaticsBase);
RuntimeAugments.StoreReferenceTypeField(gcStaticsRegion, FieldOffset, value);
return;
}
#endif
RuntimeAugments.StoreReferenceTypeField(_staticsBase + _fieldOffset, value);
RuntimeAugments.StoreReferenceTypeField(StaticsBase + FieldOffset, value);
}
}
}

Просмотреть файл

@ -2,41 +2,27 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using global::System;
using global::System.Threading;
using global::System.Reflection;
using global::System.Diagnostics;
using global::System.Collections.Generic;
using global::Internal.Runtime.Augments;
using global::Internal.Reflection.Execution;
using global::Internal.Reflection.Core.Execution;
using System;
using Internal.Runtime.Augments;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal sealed class ReferenceTypeFieldAccessorForThreadStaticFields : WritableStaticFieldAccessor
internal sealed class ReferenceTypeFieldAccessorForThreadStaticFields : ThreadStaticFieldAccessor
{
private int _threadStaticsBlockOffset;
private int _fieldOffset;
private RuntimeTypeHandle _declaringTypeHandle;
public ReferenceTypeFieldAccessorForThreadStaticFields(IntPtr cctorContext, RuntimeTypeHandle declaringTypeHandle, int threadStaticsBlockOffset, int fieldOffset, RuntimeTypeHandle fieldTypeHandle)
: base(cctorContext, fieldTypeHandle)
: base(cctorContext, declaringTypeHandle, threadStaticsBlockOffset, fieldOffset, fieldTypeHandle)
{
_threadStaticsBlockOffset = threadStaticsBlockOffset;
_fieldOffset = fieldOffset;
_declaringTypeHandle = declaringTypeHandle;
}
protected sealed override Object GetFieldBypassCctor()
{
IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(_declaringTypeHandle, _threadStaticsBlockOffset, _fieldOffset);
IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(DeclaringTypeHandle, ThreadStaticsBlockOffset, FieldOffset);
return RuntimeAugments.LoadReferenceTypeField(fieldAddress);
}
protected sealed override void UncheckedSetFieldBypassCctor(Object value)
{
IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(_declaringTypeHandle, _threadStaticsBlockOffset, _fieldOffset);
IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(DeclaringTypeHandle, ThreadStaticsBlockOffset, FieldOffset);
RuntimeAugments.StoreReferenceTypeField(fieldAddress, value);
}
}

Просмотреть файл

@ -0,0 +1,23 @@
// 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;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal abstract class RegularStaticFieldAccessor : WritableStaticFieldAccessor
{
protected RegularStaticFieldAccessor(IntPtr cctorContext, IntPtr staticsBase, int fieldOffset, bool isGcStatic, RuntimeTypeHandle fieldTypeHandle)
: base(cctorContext, fieldTypeHandle)
{
StaticsBase = staticsBase;
IsGcStatic = isGcStatic;
FieldOffset = fieldOffset;
}
protected IntPtr StaticsBase { get; }
protected bool IsGcStatic { get; }
protected int FieldOffset { get; }
}
}

Просмотреть файл

@ -2,21 +2,18 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using global::System;
using global::System.Threading;
using global::System.Reflection;
using global::System.Diagnostics;
using global::System.Collections.Generic;
using System;
using System.Reflection;
using System.Diagnostics;
using global::Internal.Runtime.Augments;
using global::Internal.Reflection.Execution;
using global::Internal.Reflection.Core.Execution;
using Internal.Runtime.Augments;
using Internal.Reflection.Core.Execution;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal abstract class StaticFieldAccessor : FieldAccessor
{
protected RuntimeTypeHandle FieldTypeHandle { get; private set; }
protected RuntimeTypeHandle FieldTypeHandle { get; }
private IntPtr _cctorContext;

Просмотреть файл

@ -0,0 +1,23 @@
// 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;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal abstract class ThreadStaticFieldAccessor : WritableStaticFieldAccessor
{
protected ThreadStaticFieldAccessor(IntPtr cctorContext, RuntimeTypeHandle declaringTypeHandle, int threadStaticsBlockOffset, int fieldOffset, RuntimeTypeHandle fieldTypeHandle)
: base(cctorContext, fieldTypeHandle)
{
ThreadStaticsBlockOffset = threadStaticsBlockOffset;
FieldOffset = fieldOffset;
DeclaringTypeHandle = declaringTypeHandle;
}
protected int ThreadStaticsBlockOffset { get; }
protected int FieldOffset { get; }
protected RuntimeTypeHandle DeclaringTypeHandle { get; }
}
}

Просмотреть файл

@ -2,33 +2,23 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using global::System;
using global::System.Threading;
using global::System.Reflection;
using global::System.Diagnostics;
using global::System.Collections.Generic;
using global::Internal.Runtime.Augments;
using global::Internal.Reflection.Execution;
using global::Internal.Reflection.Core.Execution;
using System;
using Internal.Runtime.Augments;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal sealed class ValueTypeFieldAccessorForInstanceFields : InstanceFieldAccessor
{
private int _offset;
public ValueTypeFieldAccessorForInstanceFields(int offset, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle)
: base(declaringTypeHandle, fieldTypeHandle)
public ValueTypeFieldAccessorForInstanceFields(int offsetPlusHeader, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle)
: base(declaringTypeHandle, fieldTypeHandle, offsetPlusHeader)
{
_offset = offset;
}
public sealed override int Offset => _offset - RuntimeAugments.ObjectHeaderSize;
public sealed override int Offset => OffsetPlusHeader - RuntimeAugments.ObjectHeaderSize;
protected sealed override Object UncheckedGetField(Object obj)
{
return RuntimeAugments.LoadValueTypeField(obj, _offset, this.FieldTypeHandle);
return RuntimeAugments.LoadValueTypeField(obj, OffsetPlusHeader, this.FieldTypeHandle);
}
protected sealed override object UncheckedGetFieldDirectFromValueType(TypedReference typedReference)
@ -38,7 +28,7 @@ namespace Internal.Reflection.Execution.FieldAccessors
protected sealed override void UncheckedSetField(Object obj, Object value)
{
RuntimeAugments.StoreValueTypeField(obj, _offset, value, this.FieldTypeHandle);
RuntimeAugments.StoreValueTypeField(obj, OffsetPlusHeader, value, this.FieldTypeHandle);
}
protected sealed override void UncheckedSetFieldDirectIntoValueType(TypedReference typedReference, object value)

Просмотреть файл

@ -2,56 +2,46 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using global::System;
using global::System.Reflection;
using global::System.Runtime.CompilerServices;
using global::Internal.Runtime.Augments;
using System;
using Internal.Runtime.Augments;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal sealed class ValueTypeFieldAccessorForStaticFields : WritableStaticFieldAccessor
internal sealed class ValueTypeFieldAccessorForStaticFields : RegularStaticFieldAccessor
{
private IntPtr _staticsBase;
private bool _isGcStaticsBase;
private int _fieldOffset;
public ValueTypeFieldAccessorForStaticFields(IntPtr cctorContext, IntPtr staticsBase, int fieldOffset, bool isGcStatic, RuntimeTypeHandle fieldTypeHandle)
: base(cctorContext, fieldTypeHandle)
: base(cctorContext, staticsBase, fieldOffset, isGcStatic, fieldTypeHandle)
{
_staticsBase = staticsBase;
_isGcStaticsBase = isGcStatic;
_fieldOffset = fieldOffset;
}
unsafe protected sealed override Object GetFieldBypassCctor()
{
#if CORERT
if (_isGcStaticsBase)
if (IsGcStatic)
{
// The _staticsBase variable points to a GC handle, which points at the GC statics base of the type.
// We need to perform a double indirection in a GC-safe manner.
object gcStaticsRegion = RuntimeAugments.LoadReferenceTypeField(*(IntPtr*)_staticsBase);
return RuntimeAugments.LoadValueTypeField(gcStaticsRegion, _fieldOffset, FieldTypeHandle);
object gcStaticsRegion = RuntimeAugments.LoadReferenceTypeField(*(IntPtr*)StaticsBase);
return RuntimeAugments.LoadValueTypeField(gcStaticsRegion, FieldOffset, FieldTypeHandle);
}
#endif
return RuntimeAugments.LoadValueTypeField(_staticsBase + _fieldOffset, FieldTypeHandle);
return RuntimeAugments.LoadValueTypeField(StaticsBase + FieldOffset, FieldTypeHandle);
}
unsafe protected sealed override void UncheckedSetFieldBypassCctor(Object value)
{
#if CORERT
if (_isGcStaticsBase)
if (IsGcStatic)
{
// The _staticsBase variable points to a GC handle, which points at the GC statics base of the type.
// We need to perform a double indirection in a GC-safe manner.
object gcStaticsRegion = RuntimeAugments.LoadReferenceTypeField(*(IntPtr*)_staticsBase);
RuntimeAugments.StoreValueTypeField(gcStaticsRegion, _fieldOffset, value, FieldTypeHandle);
object gcStaticsRegion = RuntimeAugments.LoadReferenceTypeField(*(IntPtr*)StaticsBase);
RuntimeAugments.StoreValueTypeField(gcStaticsRegion, FieldOffset, value, FieldTypeHandle);
return;
}
#endif
RuntimeAugments.StoreValueTypeField(_staticsBase + _fieldOffset, value, FieldTypeHandle);
RuntimeAugments.StoreValueTypeField(StaticsBase + FieldOffset, value, FieldTypeHandle);
}
}
}

Просмотреть файл

@ -2,43 +2,27 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using global::System;
using global::System.Threading;
using global::System.Reflection;
using global::System.Diagnostics;
using global::System.Collections.Generic;
using global::Internal.Runtime.Augments;
using global::Internal.Reflection.Execution;
using global::Internal.Reflection.Core.Execution;
using global::Internal.Metadata.NativeFormat;
using System;
using Internal.Runtime.Augments;
namespace Internal.Reflection.Execution.FieldAccessors
{
internal sealed class ValueTypeFieldAccessorForThreadStaticFields : WritableStaticFieldAccessor
internal sealed class ValueTypeFieldAccessorForThreadStaticFields : ThreadStaticFieldAccessor
{
private int _threadStaticsBlockOffset;
private int _fieldOffset;
private RuntimeTypeHandle _declaringTypeHandle;
public ValueTypeFieldAccessorForThreadStaticFields(IntPtr cctorContext, RuntimeTypeHandle declaringTypeHandle, int threadStaticsBlockOffset, int fieldOffset, RuntimeTypeHandle fieldTypeHandle)
: base(cctorContext, fieldTypeHandle)
: base(cctorContext, declaringTypeHandle, threadStaticsBlockOffset, fieldOffset, fieldTypeHandle)
{
_threadStaticsBlockOffset = threadStaticsBlockOffset;
_fieldOffset = fieldOffset;
_declaringTypeHandle = declaringTypeHandle;
}
protected sealed override Object GetFieldBypassCctor()
{
IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(_declaringTypeHandle, _threadStaticsBlockOffset, _fieldOffset);
IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(DeclaringTypeHandle, ThreadStaticsBlockOffset, FieldOffset);
return RuntimeAugments.LoadValueTypeField(fieldAddress, FieldTypeHandle);
}
protected sealed override void UncheckedSetFieldBypassCctor(Object value)
{
IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(_declaringTypeHandle, _threadStaticsBlockOffset, _fieldOffset);
IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(DeclaringTypeHandle, ThreadStaticsBlockOffset, FieldOffset);
RuntimeAugments.StoreValueTypeField(fieldAddress, value, FieldTypeHandle);
}
}

Просмотреть файл

@ -24,9 +24,16 @@ namespace Internal.Reflection.Extensions.NonPortable
throw new ArgumentException();
Delegate[] invokeList = del.GetInvocationList();
del = invokeList[invokeList.Length - 1];
RuntimeTypeHandle typeOfFirstParameterIfInstanceDelegate;
bool isOpenResolver;
IntPtr originalLdFtnResult = RuntimeAugments.GetDelegateLdFtnResult(del, out typeOfFirstParameterIfInstanceDelegate, out isOpenResolver);
IntPtr originalLdFtnResult = RuntimeAugments.GetDelegateLdFtnResult(del, out RuntimeTypeHandle typeOfFirstParameterIfInstanceDelegate, out bool isOpenResolver, out bool isInterpreterEntrypoint);
if (isInterpreterEntrypoint)
{
// This is a special kind of delegate where the invoke method is "ObjectArrayThunk". Typically,
// this will be a delegate that points the the LINQ Expression interpreter. We could manufacture
// a MethodInfo based on the delegate's Invoke signature, but let's just throw for now.
throw new PlatformNotSupportedException(SR.DelegateGetMethodInfo_ObjectArrayDelegate);
}
if (originalLdFtnResult == (IntPtr)0)
return null;

Просмотреть файл

@ -237,4 +237,7 @@
<data name="DelegateGetMethodInfo_NoInstantiation" xml:space="preserve">
<value>Cannot retrieve a MethodInfo for this delegate because the necessary generic instantiation was not metadata-enabled. For more information, please visit http://go.microsoft.com/fwlink/?LinkID=616868</value>
</data>
<data name="DelegateGetMethodInfo_ObjectArrayDelegate" xml:space="preserve">
<value>Cannot retrieve a MethodInfo for this delegate because the delegate target is an interpreted LINQ expression.</value>
</data>
</root>

Просмотреть файл

@ -71,10 +71,15 @@
<Compile Include="Internal\Reflection\Execution\RuntimeHandlesExtensions.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\InstanceFieldAccessor.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\LiteralFieldAccessor.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\PointerTypeFieldAccessorForInstanceFields.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\PointerTypeFieldAccessorForStaticFields.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\PointerTypeFieldAccessorForThreadStaticFields.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\RegularStaticFieldAccessor.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\ReferenceTypeFieldAccessorForInstanceFields.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\ReferenceTypeFieldAccessorForStaticFields.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\ReferenceTypeFieldAccessorForThreadStaticFields.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\StaticFieldAccessor.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\ThreadStaticFieldAccessor.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\ValueTypeFieldAccessorForInstanceFields.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\ValueTypeFieldAccessorForStaticFields.cs" />
<Compile Include="Internal\Reflection\Execution\FieldAccessors\ValueTypeFieldAccessorForThreadStaticFields.cs" />

Просмотреть файл

@ -263,11 +263,8 @@ namespace Internal.Runtime.TypeLoader
if (thunkKind == ReversePinvokeThunk)
{
// Special unsupported thunk kind. Similar behavior to the thunks generated by the delegate ILTransform for this thunk kind
RuntimeTypeHandle thDummy;
bool isOpenResolverDummy;
Action throwNotSupportedException = () => { throw new NotSupportedException(); };
return RuntimeAugments.GetDelegateLdFtnResult(throwNotSupportedException, out thDummy, out isOpenResolverDummy);
return RuntimeAugments.GetDelegateLdFtnResult(throwNotSupportedException, out RuntimeTypeHandle _, out bool __, out bool ___);
}
RuntimeTypeHandle delegateType = RuntimeAugments.GetRuntimeTypeHandleFromObjectReference(delegateObject);