Skip to content

Commit 96dc421

Browse files
authored
TypeSpec table is now minimized (#217)
1 parent 4bfebaf commit 96dc421

File tree

3 files changed

+140
-7
lines changed

3 files changed

+140
-7
lines changed

MetadataProcessor.Shared/Tables/nanoTypeSpecificationsTable.cs

Lines changed: 137 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -471,16 +471,147 @@ private void AddTypeLevelGenericParameters()
471471
ushort gpSig = _context.SignaturesTable.GetOrCreateSignatureId(gp);
472472
AddIfNew(gp, gpSig);
473473
}
474+
}
475+
}
474476

475-
// seed the *open* GenericInstanceType (e.g. Action`1<T>)
476-
var openGeneric = new GenericInstanceType(td);
477-
foreach (GenericParameter gp in td.GenericParameters)
477+
internal void RemoveEmptyItems()
478+
{
479+
var itemsToRemove = new List<TypeReference>();
480+
481+
foreach (var kvp in _idByTypeSpecifications.ToList())
482+
{
483+
TypeReference typeReference = kvp.Key;
484+
ushort sigId = kvp.Value;
485+
486+
// Get the index of this TypeSpec in the collection
487+
if (!TryGetTypeReferenceId(typeReference, out ushort index))
488+
{
489+
continue;
490+
}
491+
492+
bool hasMemberReferences = false;
493+
494+
// Check if this TypeSpec has any member references
495+
if (typeReference is GenericParameter)
496+
{
497+
// Generic parameters might be referenced without explicit member refs
498+
// Keep them for now
499+
continue;
500+
}
501+
else if (typeReference.IsArray)
502+
{
503+
// Arrays might be referenced without explicit member refs
504+
// Keep them for now
505+
continue;
506+
}
507+
else if (typeReference is ByReferenceType || typeReference is PointerType)
508+
{
509+
// ByRef and Pointer types might be referenced without explicit member refs
510+
// Keep them for now
511+
continue;
512+
}
513+
else if (typeReference is GenericInstanceType genericInstanceType)
514+
{
515+
// Check MethodReferencesTable
516+
foreach (MethodReference mr in _context.MethodReferencesTable.Items)
517+
{
518+
if (TryGetTypeReferenceId(mr.DeclaringType, out ushort referenceId)
519+
&& referenceId == index
520+
&& _context.MethodReferencesTable.TryGetMethodReferenceId(mr, out ushort _))
521+
{
522+
hasMemberReferences = true;
523+
break;
524+
}
525+
}
526+
527+
// Check MethodSpecificationTable if no refs found yet
528+
if (!hasMemberReferences)
529+
{
530+
foreach (MethodSpecification ms in _context.MethodSpecificationTable.Items)
531+
{
532+
if (TryGetTypeReferenceId(ms.DeclaringType, out ushort referenceId)
533+
&& referenceId == index
534+
&& _context.MethodSpecificationTable.TryGetMethodSpecificationId(ms, out ushort _))
535+
{
536+
hasMemberReferences = true;
537+
break;
538+
}
539+
}
540+
}
541+
542+
// Check FieldReferencesTable if no refs found yet
543+
if (!hasMemberReferences)
544+
{
545+
foreach (FieldReference fr in _context.FieldReferencesTable.Items)
546+
{
547+
if (TryGetTypeReferenceId(fr.DeclaringType, out ushort referenceId)
548+
&& referenceId == index
549+
&& _context.FieldReferencesTable.TryGetFieldReferenceId(fr, out ushort _))
550+
{
551+
hasMemberReferences = true;
552+
break;
553+
}
554+
}
555+
}
556+
557+
// Check if the ElementType is a TypeDefinition with methods/fields
558+
if (!hasMemberReferences && genericInstanceType.ElementType is TypeDefinition definition)
559+
{
560+
// Check if any of the definition's methods are in MethodDefinitionTable
561+
foreach (MethodDefinition md in definition.Methods)
562+
{
563+
if (_context.MethodDefinitionTable.TryGetMethodReferenceId(md, out ushort _))
564+
{
565+
hasMemberReferences = true;
566+
break;
567+
}
568+
}
569+
570+
// Check if any of the definition's fields are in FieldsTable
571+
if (!hasMemberReferences)
572+
{
573+
foreach (FieldDefinition fd in definition.Fields)
574+
{
575+
if (_context.FieldsTable.TryGetFieldDefinitionId(fd, false, out ushort _))
576+
{
577+
hasMemberReferences = true;
578+
break;
579+
}
580+
}
581+
}
582+
}
583+
}
584+
else
585+
{
586+
// For other TypeSpecification types (arrays, pointers, etc.)
587+
// check member references tables
588+
foreach (MemberReference mr in _context.MemberReferencesTable.Items)
589+
{
590+
try
591+
{
592+
if (TryGetTypeReferenceId(mr.DeclaringType, out ushort referenceId) && referenceId == index)
593+
{
594+
hasMemberReferences = true;
595+
break;
596+
}
597+
}
598+
catch
599+
{
600+
// ignore errors here, as the TypeSpec might not be available
601+
}
602+
}
603+
}
604+
605+
if (!hasMemberReferences)
478606
{
479-
openGeneric.GenericArguments.Add(gp);
607+
itemsToRemove.Add(typeReference);
480608
}
609+
}
481610

482-
ushort openSig = _context.SignaturesTable.GetOrCreateSignatureId(openGeneric);
483-
AddIfNew(openGeneric, openSig);
611+
// Remove items that have no member references
612+
foreach (var item in itemsToRemove)
613+
{
614+
_idByTypeSpecifications.Remove(item);
484615
}
485616
}
486617
}

MetadataProcessor.Shared/nanoAssemblyBuilder.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ public void Minimize()
248248
interfacesToRemove.Select(i => c.Interfaces.Remove(i)).ToList();
249249
}
250250

251+
_tablesContext.TypeSpecificationsTable.RemoveEmptyItems();
252+
251253
// flag minimize completed
252254
_tablesContext.MinimizeComplete = true;
253255
}

0 commit comments

Comments
 (0)