Skip to content

Commit ce892aa

Browse files
authored
Work adding support for generics (#126)
1 parent a3d79eb commit ce892aa

File tree

4 files changed

+66
-17
lines changed

4 files changed

+66
-17
lines changed

MetadataProcessor.Core/Tables/nanoSignaturesTable.cs

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -320,11 +320,21 @@ public void WriteDataType(
320320
{
321321
writer.WriteByte((byte)nanoCLR_DataType.DATATYPE_SZARRAY);
322322

323-
if (alsoWriteSubType)
323+
var array = (ArrayType)typeDefinition;
324+
325+
if (array.ElementType.IsGenericParameter)
324326
{
325-
var array = (ArrayType)typeDefinition;
327+
// ECMA 335 VI.B.4.3 Metadata
328+
writer.WriteByte((byte)nanoCLR_DataType.DATATYPE_VAR);
329+
330+
writer.WriteByte((byte)(array.ElementType as GenericParameter).Position);
331+
}
332+
else if (alsoWriteSubType)
333+
{
334+
326335
WriteDataType(array.ElementType, writer, true, expandEnumType, isTypeDefinition);
327336
}
337+
328338
return;
329339
}
330340

@@ -344,16 +354,29 @@ public void WriteDataType(
344354

345355
if (typeDefinition.IsGenericInstance)
346356
{
357+
// following ECMA-335 VI.B.4.3 Metadata
358+
writer.WriteByte((byte)nanoCLR_DataType.DATATYPE_GENERICINST);
359+
347360
var genericType = (GenericInstanceType)typeDefinition;
348-
WriteDataType(genericType.ElementType, writer, alsoWriteSubType, expandEnumType, isTypeDefinition);
361+
362+
WriteDataType(genericType.ElementType, writer, false, expandEnumType, isTypeDefinition);
363+
364+
writer.WriteByte((byte)genericType.GenericArguments.Count);
365+
366+
foreach(var a in genericType.GenericArguments)
367+
{
368+
WriteDataType(a, writer, true, expandEnumType, isTypeDefinition);
369+
}
370+
349371
return;
350372
}
351373

352374
if (typeDefinition.IsGenericParameter)
353375
{
354-
// generic parameter should be declared as object
355-
// the CLR is able to resolve to the correct type
356-
writer.WriteByte((byte)nanoCLR_DataType.DATATYPE_OBJECT);
376+
// following ECMA-335 VI.B.4.3 Metadata
377+
378+
writer.WriteByte((byte)nanoCLR_DataType.DATATYPE_MVAR);
379+
writer.WriteByte((byte)(typeDefinition as GenericParameter).Position);
357380
return;
358381
}
359382

@@ -380,7 +403,8 @@ private byte[] GetSignature(
380403
{
381404
var binaryWriter = nanoBinaryWriter.CreateBigEndianBinaryWriter(writer);
382405

383-
binaryWriter.WriteByte(0x06); // Field reference calling convention
406+
// Field reference calling convention
407+
binaryWriter.WriteByte(0x06);
384408
WriteTypeInfo(fieldReference.FieldType, binaryWriter);
385409

386410
return buffer.ToArray();
@@ -394,8 +418,25 @@ internal byte[] GetSignature(
394418
using (var writer = new BinaryWriter(buffer)) // Only Write(Byte) will be used
395419
{
396420
var binaryWriter = nanoBinaryWriter.CreateLittleEndianBinaryWriter(writer);
397-
writer.Write((byte)(methodReference.HasThis ? 0x20 : 0x00));
398421

422+
// method calling convention
423+
424+
// IMAGE_CEE_CS_CALLCONV_DEFAULT: 0x00
425+
// IMAGE_CEE_CS_CALLCONV_HASTHIS: 0x20
426+
// IMAGE_CEE_CS_CALLCONV_GENERIC: 0x10
427+
428+
byte callingConvention = methodReference.HasThis ? (byte)0x20 : (byte)0x00;
429+
callingConvention |= (byte)methodReference.CallingConvention;
430+
431+
writer.Write(callingConvention);
432+
433+
// generic parameters count, if any
434+
if (methodReference.CallingConvention == MethodCallingConvention.Generic)
435+
{
436+
writer.Write((byte)(methodReference as MethodReference).GenericParameters.Count);
437+
}
438+
439+
// regular parameter count
399440
writer.Write((byte)(methodReference.Parameters.Count));
400441

401442
WriteTypeInfo(methodReference.ReturnType, binaryWriter);
@@ -670,14 +711,6 @@ private void WriteSubTypeInfo(TypeReference typeDefinition, nanoBinaryWriter wri
670711
{
671712
writer.WriteMetadataToken((uint)referenceId << 2);
672713
}
673-
else if (typeDefinition.Resolve().HasGenericParameters &&
674-
_context.GenericParamsTable.TryGetParameterId(
675-
typeDefinition.Resolve().GenericParameters.FirstOrDefault(),
676-
out referenceId))
677-
{
678-
// TODO
679-
writer.WriteMetadataToken((uint)referenceId << 2);
680-
}
681714
else
682715
{
683716
throw new ArgumentException($"Can't find entry in type reference table for {typeDefinition.FullName}.");

MetadataProcessor.Core/Utility/nanoCLR_DataType.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,21 @@ public enum nanoCLR_DataType : byte
5252
DATATYPE_SZARRAY, // Shortcut for single dimension zero lower bound array SZARRAY <type>
5353
DATATYPE_BYREF, // BYREF <type>
5454

55+
/// <summary>
56+
/// Generic parameter in a generic type definition, represented as number
57+
/// </summary>
58+
DATATYPE_VAR,
59+
60+
/// <summary>
61+
/// Generic type instantiation
62+
/// </summary>
63+
DATATYPE_GENERICINST,
64+
65+
/// <summary>
66+
/// Generic parameter in a generic method definition, represented as number
67+
/// </summary>
68+
DATATYPE_MVAR,
69+
5570
////////////////////////////////////////
5671

5772
DATATYPE_FREEBLOCK,

MetadataProcessor.Core/nanoAssemblyBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ public void Minimize()
170170
_tablesContext.AssemblyReferenceTable.RemoveUnusedItems(set);
171171
_tablesContext.TypeReferencesTable.RemoveUnusedItems(set);
172172
_tablesContext.FieldsTable.RemoveUnusedItems(set);
173+
_tablesContext.GenericParamsTable.RemoveUnusedItems(set);
173174
_tablesContext.FieldReferencesTable.RemoveUnusedItems(set);
174175
_tablesContext.MethodDefinitionTable.RemoveUnusedItems(set);
175176
_tablesContext.MethodReferencesTable.RemoveUnusedItems(set);

version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3-
"version": "2.30",
3+
"version": "2.31",
44
"release": {
55
"branchName" : "release-v{version}",
66
"versionIncrement" : "build",

0 commit comments

Comments
 (0)