private void EmitFields() { writer.WriteLine("[Fields]"); writer.WriteLine("TypeID\tIndex\tFullName\tName\tFieldTypeID\tAddress\tAttributes\tOffset\tDataLength\tDataAddress"); foreach (var type in TypeSystem.AllTypes) { if (type.IsModule) { continue; } int index = 0; foreach (var field in type.Fields) { var symbolName = Metadata.FieldDefinition + field.FullName; if (!Linker.IsSymbolDefined(symbolName)) { continue; } var symbol = Linker.GetSymbol(symbolName); //var datasection = (field.Data != null) ? SectionKind.ROData : SectionKind.BSS; // not used yet writer.WriteLine( "{0}\t{1}\t{2}\t{3}\t{4}\t{5:x8}\t{6}\t{7}\t{8}\t{9:x8}", type.ID, index++, field.FullName, field.Name, field.FieldType.ID, symbol?.VirtualAddress ?? 0, (int)field.FieldAttributes, field.IsStatic && !field.IsLiteral ? 0 : TypeLayout.GetFieldOffset(field), // todo: missing first offset field.Data?.Length ?? 0, 0 // todo: DataAddress ); } } }
private LinkerSymbol CreateFieldDefinitions(MosaType type) { // Emit fields table var fieldsTableSymbol = Linker.DefineSymbol(Metadata.FieldsTable + type.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer1 = new EndianAwareBinaryWriter(fieldsTableSymbol.Stream, Architecture.Endianness); // 1. Number of Fields writer1.Write((uint)type.Fields.Count, TypeLayout.NativePointerSize); // 2. Pointers to Field Definitions foreach (var field in type.Fields) { // Emit field name var fieldNameSymbol = EmitStringWithLength(Metadata.NameString + field.FullName, field.Name); // Emit field definition var fieldDefSymbol = Linker.DefineSymbol(Metadata.FieldDefinition + field.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer2 = new EndianAwareBinaryWriter(fieldDefSymbol.Stream, Architecture.Endianness); // 1. Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, writer2.Position, fieldNameSymbol, 0); writer2.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (field.CustomAttributes.Count > 0) { var customAttributesTableSymbol = CreateCustomAttributesTable(field); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, writer2.Position, customAttributesTableSymbol, 0); } writer2.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes writer2.Write((uint)field.FieldAttributes, TypeLayout.NativePointerSize); // 4. Pointer to Field Type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, writer2.Position, Metadata.TypeDefinition + field.FieldType.FullName, 0); writer2.WriteZeroBytes(TypeLayout.NativePointerSize); // 5 & 6. Offset / Address + Size if (field.IsStatic && !field.IsLiteral && !type.HasOpenGenericParams) { if (Compiler.MethodScanner.IsFieldAccessed(field)) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, writer2.Position, field.FullName, 0); } writer2.WriteZeroBytes(TypeLayout.NativePointerSize); writer2.Write(field.Data?.Length ?? 0, TypeLayout.NativePointerSize); } else { writer2.WriteZeroBytes(TypeLayout.NativePointerSize); writer2.Write(TypeLayout.GetFieldOffset(field), TypeLayout.NativePointerSize); } // Add pointer to field list Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldsTableSymbol, writer1.Position, fieldDefSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); } return(fieldsTableSymbol); }
private LinkerSymbol CreateFieldDefinitions(MosaType type) { // Emit fields table var fieldsTableSymbol = Linker.CreateSymbol(type.FullName + Metadata.FieldsTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer1 = new EndianAwareBinaryWriter(fieldsTableSymbol.Stream, Architecture.Endianness); // 1. Number of Fields writer1.Write((uint)type.Fields.Count, TypeLayout.NativePointerSize); // 2. Pointers to Field Definitions foreach (MosaField field in type.Fields) { // Emit field name var fieldNameSymbol = EmitStringWithLength(field.FullName + Metadata.NameString, field.Name); // Emit field definition var fieldDefSymbol = Linker.CreateSymbol(field.FullName + Metadata.FieldDefinition, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer2 = new EndianAwareBinaryWriter(fieldDefSymbol.Stream, Architecture.Endianness); // 1. Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, (int)writer2.Position, 0, fieldNameSymbol, 0); writer2.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (field.CustomAttributes.Count > 0) { var customAttributesTableSymbol = CreateCustomAttributesTable(field); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, (int)writer2.Position, 0, customAttributesTableSymbol, 0); } writer2.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes writer2.Write((uint)field.FieldAttributes, TypeLayout.NativePointerSize); // 4. Pointer to Field Type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, (int)writer2.Position, 0, field.FieldType.FullName + Metadata.TypeDefinition, SectionKind.ROData, 0); writer2.WriteZeroBytes(TypeLayout.NativePointerSize); // 5 & 6. Offset / Address + Size if (field.IsStatic && !field.IsLiteral) { var section = (field.Data != null) ? SectionKind.ROData : SectionKind.BSS; Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, (int)writer2.Position, 0, field.FullName, section, 0); writer2.WriteZeroBytes(TypeLayout.NativePointerSize); writer2.Write((field.Data != null) ? field.Data.Length : 0, TypeLayout.NativePointerSize); } else { writer2.WriteZeroBytes(TypeLayout.NativePointerSize); writer2.Write(TypeLayout.GetFieldOffset(field), TypeLayout.NativePointerSize); } // Create another symbol with field data if any if (field.IsStatic) { // Assign a memory slot to the static & initialize it, if there's initial data set // Determine the size of the type & alignment requirements int size, alignment; Architecture.GetTypeRequirements(TypeLayout, field.FieldType, out size, out alignment); size = TypeLayout.GetFieldSize(field); // The linker section to move this field into SectionKind section = field.Data != null ? section = SectionKind.ROData : section = SectionKind.BSS; var symbol = Compiler.Linker.CreateSymbol(field.FullName, section, alignment, size); if (field.Data != null) { symbol.Stream.Write(field.Data, 0, size); } } // Add pointer to field list Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldsTableSymbol, (int)writer1.Position, 0, fieldDefSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); } // Return fieldsTableSymbol for linker usage return(fieldsTableSymbol); }