private LinkerSymbol CreatePropertyDefinitions(MosaType type) { // Emit properties table var propertiesTableSymbol = Linker.DefineSymbol(Metadata.PropertiesTable + type.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(propertiesTableSymbol.Stream, Architecture.Endianness); // 1. Number of Properties writer.Write((uint)type.Properties.Count, TypeLayout.NativePointerSize); // 2. Pointers to Property Definitions foreach (var property in type.Properties) { // Emit field name var fieldNameSymbol = EmitStringWithLength(Metadata.NameString + property.FullName, property.Name); // Emit property definition var propertyDefSymbol = Linker.DefineSymbol(Metadata.PropertyDefinition + property.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer2 = new EndianAwareBinaryWriter(propertyDefSymbol.Stream, Architecture.Endianness); // 1. Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, writer2.Position, fieldNameSymbol, 0); writer2.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (property.CustomAttributes.Count > 0) { var customAttributesTableSymbol = CreateCustomAttributesTable(property); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, writer.Position, customAttributesTableSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes writer.Write((uint)property.PropertyAttributes, TypeLayout.NativePointerSize); // 4. Pointer to Property Type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, writer2.Position, Metadata.TypeDefinition + property.PropertyType.FullName, 0); writer2.WriteZeroBytes(TypeLayout.NativePointerSize); // If the type is a property then skip linking the methods if (!type.IsInterface) { // 5. Pointer to Getter Method Definition if (property.GetterMethod != null && property.GetterMethod.HasImplementation && !property.GetterMethod.HasOpenGenericParams) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, writer2.Position, Metadata.MethodDefinition + property.GetterMethod.FullName, 0); } writer2.WriteZeroBytes(TypeLayout.NativePointerSize); // 6. Pointer to Setter Method Definition if (property.SetterMethod != null && property.SetterMethod.HasImplementation && !property.SetterMethod.HasOpenGenericParams) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, writer2.Position, Metadata.MethodDefinition + property.SetterMethod.FullName, 0); } writer2.WriteZeroBytes(TypeLayout.NativePointerSize); } else { // Fill 5 and 6 with zeros. writer.WriteZeroBytes(TypeLayout.NativePointerSize * 2); } // Add pointer to properties table Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertiesTableSymbol, writer.Position, propertyDefSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } return(propertiesTableSymbol); }
private LinkerSymbol CreateTypeDefinition(MosaType type, LinkerSymbol assemblyTableSymbol) { // Emit type table var typeNameSymbol = EmitStringWithLength(Metadata.NameString + type.FullName, type.FullName); var typeTableSymbol = Linker.DefineSymbol(Metadata.TypeDefinition + type.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(typeTableSymbol.Stream, Architecture.Endianness); // 1. Pointer to Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, typeNameSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (type.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, customAttributeListSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Type Code & Attributes writer.Write(((uint)type.TypeCode << 24) + (uint)type.TypeAttributes, TypeLayout.NativePointerSize); // 4. Size writer.Write((uint)TypeLayout.GetTypeSize(type), TypeLayout.NativePointerSize); // 5. Pointer to Assembly Definition Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, assemblyTableSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 6. Pointer to Base Type if (type.BaseType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.TypeDefinition + type.BaseType.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 7. Pointer to Declaring Type if (type.DeclaringType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.TypeDefinition + type.DeclaringType.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 8. Pointer to Element Type if (type.ElementType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.TypeDefinition + type.ElementType.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 9. Constructor that accepts no parameters, if any, for this type foreach (var method in type.Methods) { if (!method.IsConstructor || method.Signature.Parameters.Count != 0 || method.HasOpenGenericParams) { continue; } // TODO: Inline //if (Compiler.CompilerData.IsMethodInlined(method)) // continue; if (!Compiler.MethodScanner.IsMethodInvoked(method)) { break; } Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.MethodDefinition + method.FullName, 0); break; } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 10. Properties (if any) if (type.Properties.Count > 0) { var propertiesSymbol = CreatePropertyDefinitions(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, propertiesSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // If the type is not an interface continue, otherwise just pad until the end if (!type.IsInterface) { // 11. Fields (if any) if (type.Fields.Count > 0) { var fieldsSymbol = CreateFieldDefinitions(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, fieldsSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); var interfaces = type.HasOpenGenericParams ? null : GetInterfaces(type); // If the type doesn't use interfaces then skip 9 and 10 if (interfaces != null && interfaces.Count > 0) { // 12. Pointer to Interface Slots var interfaceSlotTableSymbol = CreateInterfaceSlotTable(type, interfaces); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, interfaceSlotTableSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 13. Pointer to Interface Bitmap var interfaceBitmapSymbol = CreateInterfaceBitmap(type, interfaces); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, interfaceBitmapSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } else { // Fill 12 and 13 with zeros writer.WriteZeroBytes(TypeLayout.NativePointerSize * 2); } // For the next part we'll need to get the list of methods from the MosaTypeLayout var methodList = TypeLayout.GetMethodTable(type) ?? new List <MosaMethod>(); // 14. Number of Methods writer.Write(methodList.Count, TypeLayout.NativePointerSize); // 15. Pointer to Methods foreach (var method in methodList) { Debug.Assert((!(!method.HasImplementation && method.IsAbstract)) == (method.HasImplementation || !method.IsAbstract)); if ((!(!method.HasImplementation && method.IsAbstract)) && !method.HasOpenGenericParams && !method.DeclaringType.HasOpenGenericParams //&& !Compiler.CompilerData.IsMethodInlined(method) // TODO: Inline && Compiler.MethodScanner.IsMethodInvoked(method)) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, GetMethodNameConsiderPlug(method), 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); } // 16. Pointer to Method Definitions foreach (var method in methodList) { if ((!(!method.HasImplementation && method.IsAbstract)) && !method.HasOpenGenericParams && !method.DeclaringType.HasOpenGenericParams) { // Create definition and get the symbol var methodDefinitionSymbol = CreateMethodDefinition(method); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, methodDefinitionSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); } } else { // Fill 11, 12, 13, 14 with zeros, 15 & 16 can be left out. writer.WriteZeroBytes(TypeLayout.NativePointerSize * 4); } return(typeTableSymbol); }
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); }
protected override void Finalization() { // Emit assembly list var methodLookupTable = Linker.DefineSymbol(Metadata.MethodLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new BinaryWriter(methodLookupTable.Stream); // 1. Number of methods int count = 0; writer.Write((int)0); foreach (var module in TypeSystem.Modules) { foreach (var type in module.Types.Values) { if (type.IsModule) { continue; } if (!Compiler.MethodScanner.IsTypeAllocated(type)) { continue; } var methodList = TypeLayout.GetMethodTable(type); if (methodList == null) { continue; } foreach (var method in methodList) { var targetMethodData = GetTargetMethodData(method); if (!targetMethodData.HasCode) { continue; } // 1. Pointer to Method Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.GetPosition(), targetMethodData.Method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Size of Method Linker.Link(LinkType.Size, NativePatchType, methodLookupTable, writer.GetPosition(), targetMethodData.Method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Pointer to Method Definition Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.GetPosition(), Metadata.MethodDefinition + method.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); count++; } } } writer.SetPosition(0); writer.Write(count); }