diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index a0e05277a..66507a882 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -7,6 +7,7 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; +using System.Xml.Linq; using Draco.Compiler.Api; using Draco.Compiler.Internal.OptimizingIr.Model; using Draco.Compiler.Internal.Symbols; @@ -380,15 +381,27 @@ private void EncodeAssembly() } } - private void EncodeModule(IModule module, TypeDefinitionHandle? parentModule = null, int fieldIndex = 1, int procIndex = 1) + private void EncodeModule(IModule module) { - var currentFieldIndex = fieldIndex; - var currentProcIndex = procIndex; + var fieldIndex = 1; + var procIndex = 1; + this.EncodeModule(module, parent: null, fieldIndex: ref fieldIndex, procIndex: ref procIndex); + } + + private void EncodeModule( + IModule module, + TypeDefinitionHandle? parent, + ref int fieldIndex, + ref int procIndex) + { + var startFieldIndex = fieldIndex; + var startProcIndex = procIndex; + // Go through globals foreach (var global in module.Globals) { this.EncodeGlobal(global); - currentFieldIndex++; + ++fieldIndex; } // Go through procedures @@ -402,22 +415,17 @@ private void EncodeModule(IModule module, TypeDefinitionHandle? parentModule = n // If this is the entry point, save it if (ReferenceEquals(this.assembly.EntryPoint, procedure)) this.EntryPointHandle = handle; - currentProcIndex++; + + ++procIndex; } // Compile global initializer too this.EncodeProcedure(module.GlobalInitializer, specialName: ".cctor"); - currentProcIndex++; + ++procIndex; - TypeAttributes visibility; - if (module.Symbol.Visibility == Api.Semantics.Visibility.Public) - { - visibility = parentModule is not null ? TypeAttributes.NestedPublic : TypeAttributes.Public; - } - else - { - visibility = parentModule is not null ? TypeAttributes.NestedAssembly : TypeAttributes.NotPublic; - } + var visibility = module.Symbol.Visibility == Api.Semantics.Visibility.Public + ? (parent is not null ? TypeAttributes.NestedPublic : TypeAttributes.Public) + : (parent is not null ? TypeAttributes.NestedAssembly : TypeAttributes.NotPublic); var attributes = visibility | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit | TypeAttributes.Abstract | TypeAttributes.Sealed; var name = string.IsNullOrEmpty(module.Name) ? CompilerConstants.DefaultModuleName : module.Name; @@ -428,19 +436,56 @@ private void EncodeModule(IModule module, TypeDefinitionHandle? parentModule = n @namespace: default, name: name, baseType: this.systemObjectReference, - fieldList: MetadataTokens.FieldDefinitionHandle(fieldIndex), - methodList: MetadataTokens.MethodDefinitionHandle(procIndex)); + fieldList: MetadataTokens.FieldDefinitionHandle(startFieldIndex), + methodList: MetadataTokens.MethodDefinitionHandle(startProcIndex)); // If this isn't top level module, we specify nested relationship - if (parentModule is not null) this.MetadataBuilder.AddNestedType(createdModule, parentModule.Value); + if (parent is not null) this.MetadataBuilder.AddNestedType(createdModule, parent.Value); + + // We encode every class + foreach (var @class in module.Classes.Values) + { + this.EncodeClass(@class, parent: createdModule, fieldIndex: ref fieldIndex, procIndex: ref procIndex); + } // We encode every submodule foreach (var subModule in module.Submodules.Values) { - this.EncodeModule(subModule, createdModule, currentFieldIndex, currentProcIndex); + this.EncodeModule(subModule, parent: createdModule, fieldIndex: ref fieldIndex, procIndex: ref procIndex); } } + private TypeDefinitionHandle EncodeClass( + IClass @class, + TypeDefinitionHandle? parent, + ref int fieldIndex, + ref int procIndex) + { + var startFieldIndex = fieldIndex; + var startProcIndex = procIndex; + + // TODO: Go through members + + var visibility = @class.Symbol.Visibility == Api.Semantics.Visibility.Public + ? (parent is not null ? TypeAttributes.NestedPublic : TypeAttributes.Public) + : (parent is not null ? TypeAttributes.NestedAssembly : TypeAttributes.NotPublic); + var attributes = visibility | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit | TypeAttributes.Sealed; + + // Create the type + var createdClass = this.AddTypeDefinition( + attributes: attributes, + @namespace: default, + name: @class.Name, + baseType: this.systemObjectReference, + fieldList: MetadataTokens.FieldDefinitionHandle(startFieldIndex), + methodList: MetadataTokens.MethodDefinitionHandle(startProcIndex)); + + // If this isn't top level module, we specify nested relationship + if (parent is not null) this.MetadataBuilder.AddNestedType(createdClass, parent.Value); + + return createdClass; + } + private FieldDefinitionHandle EncodeGlobal(GlobalSymbol global) { var visibility = global.Visibility switch