diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index c1548482d..f68012868 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -179,8 +179,21 @@ public EntityHandle GetEntityHandle(Symbol symbol) var blob = this.EncodeBlob(e => { var encoder = e.TypeSpecificationSignature(); - // TODO: Fix this callsite for source classes - var typeRef = this.GetEntityHandle(typeSymbol.GenericDefinition); + EntityHandle typeRef; + // TODO: Hack for source-class generics + if (typeSymbol.GenericDefinition is SourceClassSymbol sourceClass) + { + // TODO: Copypasta + // TODO: This is also horribly incorrect + typeRef = this.GetOrAddTypeReference( + parent: this.GetEntityHandle(sourceClass.ContainingSymbol), + @namespace: null, + name: sourceClass.MetadataName); + } + else + { + typeRef = this.GetEntityHandle(typeSymbol.GenericDefinition); + } var argsEncoder = encoder.GenericInstantiation( genericType: typeRef, genericArgumentCount: typeSymbol.GenericArguments.Length, @@ -809,12 +822,52 @@ private StandaloneSignatureHandle EncodeLocals( foreach (var local in locals) { var typeEncoder = localsEncoder.AddVariable().Type(); - this.EncodeSignatureType(typeEncoder, local.Symbol.Type); + if (local.Symbol.Type is SourceClassSymbol { IsGenericDefinition: true } sourceClass) + { + // TODO: That _DAMN_ ugly hack again... + // Copypasta... + var genericDef = this.GetOrAddTypeReference( + parent: this.GetEntityHandle(sourceClass.ContainingSymbol), + @namespace: null, + name: sourceClass.MetadataName); + var argsEncoder = typeEncoder.GenericInstantiation( + genericType: genericDef, + genericArgumentCount: sourceClass.GenericParameters.Length, + isValueType: sourceClass.IsValueType); + foreach (var param in sourceClass.GenericParameters) + { + this.EncodeSignatureType(argsEncoder.AddArgument(), param); + } + } + else + { + this.EncodeSignatureType(typeEncoder, local.Symbol.Type); + } } foreach (var register in registers) { var typeEncoder = localsEncoder.AddVariable().Type(); - this.EncodeSignatureType(typeEncoder, register.Type); + if (register.Type is SourceClassSymbol { IsGenericDefinition: true } sourceClass) + { + // TODO: That _DAMN_ ugly hack again... + // Copypasta... + var genericDef = this.GetOrAddTypeReference( + parent: this.GetEntityHandle(sourceClass.ContainingSymbol), + @namespace: null, + name: sourceClass.MetadataName); + var argsEncoder = typeEncoder.GenericInstantiation( + genericType: genericDef, + genericArgumentCount: sourceClass.GenericParameters.Length, + isValueType: sourceClass.IsValueType); + foreach (var param in sourceClass.GenericParameters) + { + this.EncodeSignatureType(argsEncoder.AddArgument(), param); + } + } + else + { + this.EncodeSignatureType(typeEncoder, register.Type); + } } })); } @@ -882,8 +935,23 @@ public void EncodeSignatureType(SignatureTypeEncoder encoder, TypeSymbol type) // Generic instantiation Debug.Assert(type.GenericDefinition is not null); + // TODO: That ugly hack again... + EntityHandle typeRef; + if (type.GenericDefinition is SourceClassSymbol sourceClass2) + { + // TODO: Copypasta + // TODO: This is also horribly incorrect + typeRef = this.GetOrAddTypeReference( + parent: this.GetEntityHandle(sourceClass2.ContainingSymbol), + @namespace: null, + name: sourceClass2.MetadataName); + } + else + { + typeRef = this.GetEntityHandle(type.GenericDefinition); + } var genericsEncoder = encoder.GenericInstantiation( - genericType: this.GetEntityHandle(type.GenericDefinition), + genericType: typeRef, genericArgumentCount: type.GenericArguments.Length, isValueType: type.IsValueType); foreach (var arg in type.GenericArguments)