diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index a9cacb0ad..01609c818 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -464,7 +464,18 @@ private TypeDefinitionHandle EncodeClass( var startFieldIndex = fieldIndex; var startProcIndex = procIndex; - foreach (var proc in @class.Procedures.Values) this.EncodeProcedure(proc); + foreach (var proc in @class.Procedures.Values) + { + this.EncodeProcedure(proc); + ++procIndex; + } + + foreach (var field in @class.Fields) + { + + this.EncodeField(field); + ++fieldIndex; + } // TODO: Go through the rest of the members @@ -490,13 +501,7 @@ private TypeDefinitionHandle EncodeClass( private FieldDefinitionHandle EncodeGlobal(GlobalSymbol global) { - var visibility = global.Visibility switch - { - Api.Semantics.Visibility.Public => FieldAttributes.Public, - Api.Semantics.Visibility.Internal => FieldAttributes.Assembly, - Api.Semantics.Visibility.Private => FieldAttributes.Private, - _ => throw new ArgumentOutOfRangeException(nameof(global.Visibility)), - }; + var visibility = GetFieldVisibility(global.Visibility); // Definition return this.AddFieldDefinition( @@ -505,15 +510,21 @@ private FieldDefinitionHandle EncodeGlobal(GlobalSymbol global) signature: this.EncodeGlobalSignature(global)); } + private FieldDefinitionHandle EncodeField(FieldSymbol field) + { + var visibility = GetFieldVisibility(field.Visibility); + var mutability = field.IsMutable ? default : FieldAttributes.InitOnly; + + // Definition + return this.AddFieldDefinition( + attributes: visibility | mutability, + name: field.Name, + signature: this.EncodeFieldSignature(field)); + } + private MethodDefinitionHandle EncodeProcedure(IProcedure procedure) { - var visibility = procedure.Symbol.Visibility switch - { - Api.Semantics.Visibility.Public => MethodAttributes.Public, - Api.Semantics.Visibility.Internal => MethodAttributes.Assembly, - Api.Semantics.Visibility.Private => MethodAttributes.Private, - _ => throw new ArgumentOutOfRangeException(nameof(procedure.Symbol.Visibility)), - }; + var visibility = GetMethodVisibility(procedure.Symbol.Visibility); // Encode instructions var cilCodegen = new CilCodegen(this, procedure); @@ -580,6 +591,9 @@ private MethodDefinitionHandle EncodeProcedure(IProcedure procedure) private BlobHandle EncodeGlobalSignature(GlobalSymbol global) => this.EncodeBlob(e => this.EncodeSignatureType(e.Field().Type(), global.Type)); + private BlobHandle EncodeFieldSignature(FieldSymbol field) => + this.EncodeBlob(e => this.EncodeSignatureType(e.Field().Type(), field.Type)); + private BlobHandle EncodeProcedureSignature(IProcedure procedure) => this.EncodeBlob(e => { e @@ -756,4 +770,20 @@ private void WritePe(Stream peStream) var contentId = peBuilder.Serialize(peBlob); peBlob.WriteContentTo(peStream); } + + private static FieldAttributes GetFieldVisibility(Api.Semantics.Visibility visibility) => visibility switch + { + Api.Semantics.Visibility.Public => FieldAttributes.Public, + Api.Semantics.Visibility.Internal => FieldAttributes.Assembly, + Api.Semantics.Visibility.Private => FieldAttributes.Private, + _ => throw new ArgumentOutOfRangeException(nameof(visibility)), + }; + + private static MethodAttributes GetMethodVisibility(Api.Semantics.Visibility visibility) => visibility switch + { + Api.Semantics.Visibility.Public => MethodAttributes.Public, + Api.Semantics.Visibility.Internal => MethodAttributes.Assembly, + Api.Semantics.Visibility.Private => MethodAttributes.Private, + _ => throw new ArgumentOutOfRangeException(nameof(visibility)), + }; } diff --git a/src/Draco.Compiler/Internal/OptimizingIr/ClassCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/ClassCodegen.cs index 1cadbf450..679ea255a 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/ClassCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/ClassCodegen.cs @@ -50,8 +50,7 @@ public override void VisitFunction(FunctionSymbol functionSymbol) public override void VisitField(FieldSymbol fieldSymbol) { - // TODO - throw new NotImplementedException(); + // No-op, the Class model reads it up from the symbol } // TODO: Copypasta from ModuleCodegen diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs index 6c9d8eab8..f425d5d69 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -24,6 +25,11 @@ internal sealed class Class : IClass public IReadOnlyList Generics => this.Symbol.GenericParameters; + public IReadOnlyList Fields => InterlockedUtils.InitializeDefault( + ref this.fields, + () => this.Symbol.DefinedMembers.OfType().ToImmutableArray()); + private ImmutableArray fields; + public IReadOnlyDictionary Procedures => this.procedures; private readonly Dictionary procedures = new(); diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs index c780fd19e..19e387f21 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs @@ -45,9 +45,13 @@ internal interface IClass // TODO: Base class // TODO: Interfaces? (we might wanna keep them external) // TODO: Nested classes - // TODO: fields // TODO: properties + /// + /// The fields defined on this class. + /// + public IReadOnlyList Fields { get; } + /// /// The procedures defined on this class. ///