Example #1
0
        private void ScheduleMethods(MosaType type)
        {
            var currentType = type;

            var slots = new bool[TypeLayout.GetMethodTable(type).Count];

            while (currentType != null)
            {
                foreach (var method in currentType.Methods)
                {
                    bool contains;

                    lock (invokedMethods)
                    {
                        contains = invokedMethods.Contains(method);
                    }

                    if (contains)
                    {
                        int slot = TypeLayout.GetMethodSlot(method);

                        if (slots[slot])
                        {
                            continue;
                        }

                        slots[slot] = true;

                        ScheduleMethod(method);
                    }
                }

                currentType = currentType.BaseType;                 // EXPLORE: base types may not need to be considered
            }
        }
Example #2
0
        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;
                }

                var targetMethodData = GetTargetMethodData(method);

                if (targetMethodData.HasCode)
                {
                    Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.MethodDefinition + targetMethodData.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)
                {
                    var targetMethodData = GetTargetMethodData(method);

                    if (targetMethodData.HasCode)
                    {
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, targetMethodData.Method.FullName, 0);
                    }
                    writer.WriteZeroBytes(TypeLayout.NativePointerSize);
                }

                // 16. Pointer to Method Definitions
                foreach (var method in methodList)
                {
                    // 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);
        }
        protected void CreateMethodExceptionLookupTable()
        {
            // Emit assembly list
            var methodLookupTable = Linker.CreateSymbol(Metadata.MethodExceptionLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer            = new EndianAwareBinaryWriter(methodLookupTable.Stream, Architecture.Endianness);

            // 1. Number of methods
            int count = 0;

            foreach (var module in TypeSystem.Modules)
            {
                foreach (var type in module.Types.Values)
                {
                    if (type.IsModule)
                    {
                        continue;
                    }

                    var methodList = TypeLayout.GetMethodTable(type);

                    if (methodList == null)
                    {
                        continue;
                    }

                    foreach (var method in methodList)
                    {
                        if (method.IsAbstract)
                        {
                            continue;
                        }

                        if (method.ExceptionHandlers.Count == 0)
                        {
                            continue;
                        }

                        count++;
                    }
                }
            }
            writer.Write(count);

            foreach (var module in TypeSystem.Modules)
            {
                foreach (var type in module.Types.Values)
                {
                    if (type.IsModule)
                    {
                        continue;
                    }

                    var methodList = TypeLayout.GetMethodTable(type);

                    if (methodList == null)
                    {
                        continue;
                    }

                    foreach (var method in methodList)
                    {
                        if (method.IsAbstract)
                        {
                            continue;
                        }

                        if (method.ExceptionHandlers.Count == 0)
                        {
                            continue;
                        }

                        // 1. Pointer to Method
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, (int)writer.Position, 0, method.FullName, SectionKind.Text, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 2. Size of Method
                        Linker.Link(LinkType.Size, NativePatchType, methodLookupTable, (int)writer.Position, 0, method.FullName, SectionKind.Text, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 3. Pointer to Method Definition
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, (int)writer.Position, 0, method.FullName + Metadata.MethodDefinition, SectionKind.ROData, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);
                    }
                }
            }
        }
        protected void CreateMethodExceptionLookupTable()
        {
            // Emit assembly list
            var methodLookupTable = Linker.DefineSymbol(Metadata.MethodExceptionLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer            = new EndianAwareBinaryWriter(methodLookupTable.Stream, Architecture.Endianness);

            // 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)
                    {
                        if ((!method.HasImplementation && method.IsAbstract) || method.HasOpenGenericParams || method.DeclaringType.HasOpenGenericParams)
                        {
                            continue;
                        }

                        if (method.ExceptionHandlers.Count == 0)
                        {
                            continue;
                        }

                        if (!Compiler.MethodScanner.IsMethodInvoked(method))
                        {
                            continue;
                        }

                        // 1. Pointer to Method
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.Position, method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 2. Size of Method
                        Linker.Link(LinkType.Size, NativePatchType, methodLookupTable, writer.Position, method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 3. Pointer to Method Definition
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.Position, Metadata.MethodDefinition + method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        count++;
                    }
                }
            }

            writer.Position = 0;
            writer.Write(count);

            // emit null entry (FUTURE)
            //writer.WriteZeroBytes(TypeLayout.NativePointerSize * 3);
        }
Example #5
0
        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(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);
        }
Example #6
0
        private LinkerSymbol CreateTypeDefinition(MosaType type, LinkerSymbol assemblyTableSymbol)
        {
            // Emit type table
            var typeNameSymbol       = EmitStringWithLength(Metadata.NameString + type.FullName, type.FullName);
            var typeDefinitionSymbol = Linker.DefineSymbol(Metadata.TypeDefinition + type.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer = new BinaryWriter(typeDefinitionSymbol.Stream);

            // 1. Pointer to Name
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), typeNameSymbol, (int)Compiler.ObjectHeaderSize);
            writer.WriteZeroBytes(NativePointerSize);

            // 2. Pointer to Custom Attributes
            if (type.CustomAttributes.Count > 0)
            {
                var customAttributeListSymbol = CreateCustomAttributesTable(type);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), customAttributeListSymbol, 0);
            }
            writer.WriteZeroBytes(NativePointerSize);

            // 3. Type Code & Attributes
            writer.Write(((uint)type.TypeCode << 24) + (uint)type.TypeAttributes, NativePointerSize);

            // 4. Size
            writer.Write((uint)TypeLayout.GetTypeSize(type), NativePointerSize);

            // 5. Pointer to Assembly Definition
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), assemblyTableSymbol, 0);
            writer.WriteZeroBytes(NativePointerSize);

            // 6. Pointer to Base Type
            if (type.BaseType != null)
            {
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.TypeDefinition + type.BaseType.FullName, 0);
            }
            writer.WriteZeroBytes(NativePointerSize);

            // 7. Pointer to Declaring Type
            if (type.DeclaringType != null)
            {
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.TypeDefinition + type.DeclaringType.FullName, 0);
            }
            writer.WriteZeroBytes(NativePointerSize);

            // 8. Pointer to Element Type
            if (type.ElementType != null)
            {
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.TypeDefinition + type.ElementType.FullName, 0);
            }
            writer.WriteZeroBytes(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;
                }

                var targetMethodData = GetTargetMethodData(method);

                if (targetMethodData.HasCode)
                {
                    Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.MethodDefinition + targetMethodData.Method.FullName, 0);
                }

                break;
            }
            writer.WriteZeroBytes(NativePointerSize);

            // 10. Properties (if any)
            if (type.Properties.Count > 0)
            {
                var propertiesSymbol = CreatePropertyDefinitions(type);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), propertiesSymbol, 0);
            }
            writer.WriteZeroBytes(NativePointerSize);

            LinkerSymbol interfaceSlotTableSymbol = null;

            // 11. Fields Definitions
            if (!type.IsInterface && type.Fields.Count > 0)
            {
                var fieldsSymbol = CreateFieldDefinitions(type);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), fieldsSymbol, 0);
            }
            writer.WriteZeroBytes(NativePointerSize);

            var interfaces = type.IsInterface || type.HasOpenGenericParams ? null : GetInterfaces(type);

            if (interfaces != null && interfaces.Count == 0)
            {
                interfaces = null;
            }

            // 12. Pointer to Interface Slots
            if (interfaces != null)
            {
                interfaceSlotTableSymbol = CreateInterfaceSlotTable(type, interfaces);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), interfaceSlotTableSymbol, 0);
            }
            writer.WriteZeroBytes(NativePointerSize);

            // 13. Pointer to Interface Bitmap
            if (interfaces != null)
            {
                var interfaceBitmapSymbol = CreateInterfaceBitmap(type, interfaces);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), interfaceBitmapSymbol, 0);
            }
            writer.WriteZeroBytes(NativePointerSize);

            var methodList = TypeLayout.GetMethodTable(type);

            // 14. Number of Methods
            writer.Write(methodList == null ? 0 : methodList.Count, NativePointerSize);

            // 15. Method Table
            if (methodList != null)
            {
                foreach (var method in methodList)
                {
                    var targetMethodData = GetTargetMethodData(method);

                    if (targetMethodData.HasCode)
                    {
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), targetMethodData.Method.FullName, 0);
                    }
                    writer.WriteZeroBytes(NativePointerSize);
                }
            }

            // 16. Method Definition Table
            if (!type.IsInterface && methodList != null)
            {
                foreach (var method in methodList)
                {
                    // Create definition and get the symbol
                    var methodDefinitionSymbol = CreateMethodDefinition(method);

                    Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), methodDefinitionSymbol, 0);
                    writer.WriteZeroBytes(NativePointerSize);
                }
            }

            return(typeDefinitionSymbol);
        }
Example #7
0
        protected void CreateMethodExceptionLookupTable()
        {
            // Emit assembly list
            var exceptionMethodLookupTable = Linker.DefineSymbol(Metadata.MethodExceptionLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer = new EndianAwareBinaryWriter(exceptionMethodLookupTable.Stream, Architecture.Endianness);

            // 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;
                        }

                        if (!targetMethodData.HasProtectedRegions)
                        {
                            continue;
                        }

                        // 1. Pointer to Method
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, exceptionMethodLookupTable, writer.Position, targetMethodData.Method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 2. Size of Method
                        Linker.Link(LinkType.Size, NativePatchType, exceptionMethodLookupTable, writer.Position, targetMethodData.Method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 3. Pointer to Method Definition
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, exceptionMethodLookupTable, writer.Position, Metadata.MethodDefinition + method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        count++;
                    }
                }
            }

            writer.Position = 0;
            writer.Write(count);

            // emit null entry (FUTURE)
            //writer.WriteZeroBytes(TypeLayout.NativePointerSize * 3);
        }