private LinkerSymbol CreateInterfaceMethodTable(MosaType type, MosaType interfaceType) { // Emit interface method table var interfaceMethodTableSymbol = Linker.DefineSymbol(Metadata.InterfaceMethodTable + type.FullName + "$" + interfaceType.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(interfaceMethodTableSymbol.Stream, Architecture.Endianness); var interfaceMethodTable = TypeLayout.GetInterfaceTable(type, interfaceType) ?? new MosaMethod[0]; // 1. Number of Interface Methods writer.Write((uint)interfaceMethodTable.Length, TypeLayout.NativePointerSize); // 2. Pointer to Interface Type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, interfaceMethodTableSymbol, writer.Position, Metadata.TypeDefinition + interfaceType.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Pointers to Method Definitions foreach (var method in interfaceMethodTable) { // Create definition and get the symbol var methodDefinitionSymbol = CreateMethodDefinition(method); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, interfaceMethodTableSymbol, writer.Position, methodDefinitionSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } return(interfaceMethodTableSymbol); }
private LinkerSymbol CreateCustomAttributeArgument(string symbolName, int count, string name, MosaCustomAttribute.Argument arg, bool isField) { string nameForSymbol = name ?? count.ToString(); nameForSymbol = symbolName + ":" + nameForSymbol; var symbol = Linker.DefineSymbol(Metadata.CustomAttributeArgument + nameForSymbol, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer1 = new EndianAwareBinaryWriter(symbol.Stream, Architecture.Endianness); // 1. Pointer to name (if named) if (name != null) { var nameSymbol = EmitStringWithLength(Metadata.NameString + nameForSymbol, name); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, symbol, writer1.Position, nameSymbol, 0); } writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Is Argument A Field writer1.Write(isField, TypeLayout.NativePointerSize); // 3. Argument Type Pointer Linker.Link(LinkType.AbsoluteAddress, NativePatchType, symbol, writer1.Position, Metadata.TypeDefinition + arg.Type.FullName, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 4. Argument Size writer1.Write(ComputeArgumentSize(arg.Type, arg.Value), TypeLayout.NativePointerSize); // 5. Argument Value WriteArgument(writer1, symbol, arg.Type, arg.Value); return(symbol); }
private LinkerSymbol CreateParameterDefinition(MosaParameter parameter) { // Emit parameter name var parameterNameSymbol = EmitStringWithLength(Metadata.NameString + parameter, parameter.FullName); // Emit parameter table var parameterTableSymbol = Linker.DefineSymbol(Metadata.MethodDefinition + parameter.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(parameterTableSymbol.Stream, Architecture.Endianness); // 1. Pointer to Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, parameterTableSymbol, writer.Position, parameterNameSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (parameter.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(parameter); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, parameterTableSymbol, writer.Position, customAttributeListSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes writer.Write((uint)parameter.ParameterAttributes, TypeLayout.NativePointerSize); // 4. Pointer to Parameter Type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, parameterTableSymbol, writer.Position, Metadata.TypeDefinition + parameter.ParameterType.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); return(parameterTableSymbol); }
private LinkerSymbol CreateAssemblyDefinition(MosaModule module) { // Emit assembly name var assemblyNameSymbol = EmitStringWithLength(Metadata.NameString + module.Assembly, module.Assembly); // Emit assembly table var assemblyTableSymbol = Linker.DefineSymbol(Metadata.AssemblyDefinition + module.Assembly, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(assemblyTableSymbol.Stream, Architecture.Endianness); // 1. Pointer to Assembly Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, writer.Position, assemblyNameSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (module.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(module); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, writer.Position, customAttributeListSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes - IsReflectionOnly (32bit length) uint flags = 0x0; if (module.IsReflectionOnly) { flags |= 0x1; } writer.Write(flags, TypeLayout.NativePointerSize); // 4. Number of Types uint count = 0; writer.WriteZeroBytes(4); // 5. Pointers to Types foreach (var type in module.Types.Values) { if (type.IsModule) { continue; } var typeTableSymbol = CreateTypeDefinition(type, assemblyTableSymbol); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, writer.Position, typeTableSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); count++; } writer.Position = 3 * TypeLayout.NativePointerSize; writer.Write(count, TypeLayout.NativePointerSize); return(assemblyTableSymbol); }
private LinkerSymbol CreateCustomAttributesTable(MosaUnit unit) { var symbolName = Metadata.CustomAttributesTable + unit.FullName; var customAttributesTableSymbol = Linker.GetSymbol(symbolName); if (customAttributesTableSymbol.Size != 0) { return(customAttributesTableSymbol); } // Emit custom attributes table customAttributesTableSymbol = Linker.DefineSymbol(symbolName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(customAttributesTableSymbol.Stream, Architecture.Endianness); // 1. Number of Custom Attributes writer.Write(unit.CustomAttributes.Count, TypeLayout.NativePointerSize); // 2. Pointers to Custom Attributes for (int i = 0; i < unit.CustomAttributes.Count; i++) { // Get custom attribute var ca = unit.CustomAttributes[i]; // Build definition var customAttributeTableSymbol = CreateCustomAttribute(unit, ca, i); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributesTableSymbol, writer.Position, customAttributeTableSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } return(customAttributesTableSymbol); }
protected void WriteSymbolSection(Section section) { Debug.Assert(section == symbolSection); // first entry is completely filled with zeros writer.WriteZeroBytes(SymbolEntry.GetEntrySize(linkerFormatType)); uint count = 1; foreach (var symbol in linker.Symbols) { var symbolEntry = new SymbolEntry() { Name = AddToStringTable(symbol.Name), Value = symbol.VirtualAddress, Size = symbol.Size, SymbolBinding = SymbolBinding.Global, SymbolVisibility = SymbolVisibility.Default, SymbolType = symbol.SectionKind == SectionKind.Text ? SymbolType.Function : SymbolType.Object, SectionHeaderTableIndex = GetSection(symbol.SectionKind).Index }; symbolEntry.Write(linkerFormatType, writer); symbolTableOffset.Add(symbol, count); count++; } section.Size = (uint)(count * SymbolEntry.GetEntrySize(linkerFormatType)); }
private LinkerSymbol CreateCustomAttributesTable(MosaUnit unit) { // Emit custom attributes table var customAttributesTableSymbol = Linker.CreateSymbol(unit.FullName + Metadata.CustomAttributesTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer1 = new EndianAwareBinaryWriter(customAttributesTableSymbol.Stream, Architecture.Endianness); // 1. Number of Custom Attributes writer1.Write(unit.CustomAttributes.Count, TypeLayout.NativePointerSize); // 2. Pointers to Custom Attributes // Create the definitions along the way for (int i = 0; i < unit.CustomAttributes.Count; i++) { // Get custom attribute var ca = unit.CustomAttributes[i]; // Build definition var customAttributeTableSymbol = CreateCustomAttribute(unit, ca, i); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributesTableSymbol, (int)writer1.Position, 0, customAttributeTableSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); } // Return customAttributesTableSymbol for linker usage return(customAttributesTableSymbol); }
private void EmitProtectedRegionTable() { var trace = CreateTraceLog("Regions"); var protectedRegionTableSymbol = MethodCompiler.Linker.DefineSymbol(Metadata.ProtectedRegionTable + MethodCompiler.Method.FullName, SectionKind.ROData, NativeAlignment, 0); var writer = new EndianAwareBinaryWriter(protectedRegionTableSymbol.Stream, Architecture.Endianness); int sectioncount = 0; // 1. Number of Regions (filled in later) writer.Write((uint)0); foreach (var region in MethodCompiler.ProtectedRegions) { var handler = (uint)MethodCompiler.GetPosition(region.Handler.HandlerStart); trace?.Log($"Handler: {region.Handler.TryStart.ToString("X4")} to {region.Handler.TryEnd.ToString("X4")} Handler: {region.Handler.HandlerStart.ToString("X4")} Offset: [{handler.ToString("X4")}]"); var sections = new List <Tuple <int, int> >(); foreach (var block in region.IncludedBlocks) { // Check if block continues to exist if (!BasicBlocks.Contains(block)) { continue; } int start = MethodCompiler.GetPosition(block.Label); int end = MethodCompiler.GetPosition(block.Label + 0x0F000000); trace?.Log($" Block: {block} [{start.ToString()}-{end.ToString()}]"); AddSection(sections, start, end); } foreach (var s in sections) { int start = s.Item1; int end = s.Item2; sectioncount++; var name = Metadata.ProtectedRegionTable + MethodCompiler.Method.FullName + "$" + sectioncount.ToString(); var protectedRegionDefinition = CreateProtectedRegionDefinition(name, (uint)start, (uint)end, handler, region.Handler.ExceptionHandlerType, region.Handler.Type); MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, NativePatchType, protectedRegionTableSymbol, writer.Position, protectedRegionDefinition, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); trace?.Log($" Section: [{start.ToString()}-{end.ToString()}]"); } } // 1. Number of Regions (now put the real number) writer.Position = 0; writer.Write(sectioncount); }
private LinkerSymbol CreateCustomAttribute(MosaUnit unit, MosaCustomAttribute ca, int position) { // Emit custom attribute list string name = unit.FullName + ">>" + position.ToString() + ":" + ca.Constructor.DeclaringType.Name; var customAttributeSymbol = Linker.DefineSymbol(Metadata.CustomAttribute + name, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer1 = new EndianAwareBinaryWriter(customAttributeSymbol.Stream, Architecture.Endianness); // 1. Pointer to Attribute Type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributeSymbol, writer1.Position, Metadata.TypeDefinition + ca.Constructor.DeclaringType.FullName, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Constructor Method Definition Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributeSymbol, writer1.Position, Metadata.MethodDefinition + ca.Constructor.FullName, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Number of Arguments (Both unnamed and named) writer1.Write((uint)(ca.Arguments.Length + ca.NamedArguments.Length), TypeLayout.NativePointerSize); // 4. Pointers to Custom Attribute Arguments (Both unnamed and named) for (int i = 0; i < ca.Arguments.Length; i++) { // Build definition var customAttributeArgumentSymbol = CreateCustomAttributeArgument(name, i, null, ca.Arguments[i], false); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributeSymbol, writer1.Position, customAttributeArgumentSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); } foreach (var namedArg in ca.NamedArguments) { // Build definition var customAttributeArgumentSymbol = CreateCustomAttributeArgument(name, 0, namedArg.Name, namedArg.Argument, namedArg.IsField); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributeSymbol, writer1.Position, customAttributeArgumentSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); } return(customAttributeSymbol); }
private LinkerSymbol EmitStringWithLength(string name, string value) { // Strings are now going to be embedded objects since they are immutable var symbol = Linker.DefineSymbol(name, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(symbol.Stream, Architecture.Endianness); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, symbol, writer.Position, Metadata.TypeDefinition + "System.String", 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize * 2); writer.Write(value.Length, TypeLayout.NativePointerSize); writer.Write(Encoding.Unicode.GetBytes(value)); return(symbol); }
private void CreateDefinitionTables() { // Emit assembly list var assemblyListSymbol = Linker.DefineSymbol(Metadata.AssembliesTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(assemblyListSymbol.Stream, Architecture.Endianness); // 1. Number of Assemblies writer.Write((uint)TypeSystem.Modules.Count, TypeLayout.NativePointerSize); // 2. Pointers to Assemblies foreach (var module in TypeSystem.Modules) { var assemblyTableSymbol = CreateAssemblyDefinition(module); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyListSymbol, writer.Position, assemblyTableSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } }
private void WriteSymbolSection(Section section, EndianAwareBinaryWriter writer) { Debug.Assert(section == symbolSection); // first entry is completely filled with zeros writer.WriteZeroBytes(SymbolEntry.GetEntrySize(linkerFormatType)); uint count = 1; foreach (var symbol in linker.Symbols) { if (symbol.SectionKind == SectionKind.Unknown && symbol.LinkRequests.Count == 0) { continue; } Debug.Assert(symbol.SectionKind != SectionKind.Unknown, "symbol.SectionKind != SectionKind.Unknown"); if (!(symbol.IsExternalSymbol || linker.EmitAllSymbols)) { continue; } var symbolEntry = new SymbolEntry() { Name = AddToStringTable(symbol.ExternalSymbolName ?? symbol.Name), Value = symbol.VirtualAddress, Size = symbol.Size, SymbolBinding = SymbolBinding.Global, SymbolVisibility = SymbolVisibility.Default, SymbolType = symbol.SectionKind == SectionKind.Text ? SymbolType.Function : SymbolType.Object, SectionHeaderTableIndex = GetSection(symbol.SectionKind).Index }; symbolEntry.Write(linkerFormatType, writer); symbolTableOffset.Add(symbol, count); count++; } section.Size = count * SymbolEntry.GetEntrySize(linkerFormatType); }
private LinkerSymbol CreateInterfaceSlotTable(MosaType type) { // Emit interface slot table var interfaceSlotTableSymbol = Linker.CreateSymbol(type.FullName + Metadata.InterfaceSlotTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer1 = new EndianAwareBinaryWriter(interfaceSlotTableSymbol.Stream, Architecture.Endianness); var slots = new List <MosaType>(TypeLayout.Interfaces.Count); foreach (MosaType interfaceType in TypeLayout.Interfaces) { if (type.Interfaces.Contains(interfaceType)) { slots.Add(interfaceType); } else { slots.Add(null); } } // 1. Number of Interface slots writer1.Write((uint)slots.Count, TypeLayout.NativePointerSize); // 2. Pointers to Interface Method Tables foreach (MosaType interfaceType in slots) { if (interfaceType != null) { var interfaceMethodTableSymbol = CreateInterfaceMethodTable(type, interfaceType); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, interfaceSlotTableSymbol, (int)writer1.Position, 0, interfaceMethodTableSymbol, 0); } writer1.WriteZeroBytes(TypeLayout.NativePointerSize); } // Return interfaceSlotTableSymbol for linker usage return(interfaceSlotTableSymbol); }
private LinkerSymbol CreateProtectedRegionDefinition(string name, uint start, uint end, uint handler, ExceptionHandlerType handlerType, MosaType exceptionType) { // Emit parameter table var protectedRegionDefinitionSymbol = MethodCompiler.Linker.DefineSymbol(name, SectionKind.ROData, 0 /*TypeLayout.NativePointerAlignment*/, 0); var writer1 = new EndianAwareBinaryWriter(protectedRegionDefinitionSymbol.Stream, Architecture.Endianness); // 1. Offset to start writer1.Write(start, TypeLayout.NativePointerSize); // 2. Offset to end writer1.Write(end, TypeLayout.NativePointerSize); // 3. Offset to handler writer1.Write(handler, TypeLayout.NativePointerSize); // 4. Handler type writer1.Write((uint)handlerType, TypeLayout.NativePointerSize); // 5. Exception object type if (handlerType == ExceptionHandlerType.Exception) { // Store method table pointer of the exception object type // The VES exception runtime will uses this to compare exception object types Linker.Link(LinkType.AbsoluteAddress, NativePatchType, protectedRegionDefinitionSymbol, writer1.Position, Metadata.TypeDefinition + exceptionType.FullName, 0); } else if (handlerType == ExceptionHandlerType.Filter) { // TODO: There are no plans in the short term to support filtered exception clause as C# does not use them } else { } writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // Return protectedRegionSymbol for linker usage return(protectedRegionDefinitionSymbol); }
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); }
private LinkerSymbol CreateMethodDefinition(MosaMethod method) { var symbolName = Metadata.MethodDefinition + method.FullName; var methodTableSymbol = Linker.GetSymbol(symbolName); if (methodTableSymbol.Size != 0) { return(methodTableSymbol); } // Emit method name var methodNameSymbol = EmitStringWithLength(Metadata.NameString + method.FullName, method.FullName); // Emit method table methodTableSymbol = Linker.DefineSymbol(symbolName, SectionKind.ROData, TypeLayout.NativePointerAlignment, (method.Signature.Parameters.Count + 9) * TypeLayout.NativePointerSize); var writer = new EndianAwareBinaryWriter(methodTableSymbol.Stream, Architecture.Endianness); // 1. Pointer to Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, methodNameSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (method.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(method); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, customAttributeListSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes writer.Write((uint)method.MethodAttributes, TypeLayout.NativePointerSize); var targetMethodData = GetTargetMethodData(method); // 4. Local Stack Size (16 Bits) && Parameter Stack Size (16 Bits) writer.Write(targetMethodData.LocalMethodStackSize | (targetMethodData.ParameterStackSize << 16), TypeLayout.NativePointerSize); // 5. Pointer to Method if (targetMethodData.HasCode) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, targetMethodData.Method.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 6. Pointer to return type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, Metadata.TypeDefinition + method.Signature.ReturnType.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 7. Pointer to Exception Handler Table if (targetMethodData.HasProtectedRegions && targetMethodData.HasCode) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, Metadata.ProtectedRegionTable + targetMethodData.Method.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 8. Pointer to GC Tracking information // TODO: This has yet to be designed. writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 9. Number of Parameters writer.Write((uint)method.Signature.Parameters.Count, TypeLayout.NativePointerSize); // 10. Pointers to Parameter Definitions foreach (var parameter in method.Signature.Parameters) { // Create definition and get the symbol var parameterDefinitionSymbol = CreateParameterDefinition(parameter); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, parameterDefinitionSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } return(methodTableSymbol); }
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 interface then skip linking the methods if (!type.IsInterface) { // TODO: Replace .HasImpelement with .HasCode // 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 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 CreateMethodDefinition(MosaMethod method) { // Emit method name var methodNameSymbol = EmitStringWithLength(method.FullName + Metadata.NameString, method.FullName); // Emit method table var methodTableSymbol = Linker.CreateSymbol(method.FullName + Metadata.MethodDefinition, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer1 = new EndianAwareBinaryWriter(methodTableSymbol.Stream, Architecture.Endianness); // 1. Pointer to Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, methodNameSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (method.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(method); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, customAttributeListSymbol, 0); } writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes writer1.Write((uint)method.MethodAttributes, TypeLayout.NativePointerSize); // 4. Local Stack Size (16 Bits) && Parameter Stack Size (16 Bits) int value = TypeLayout.GetMethodStackSize(method) | (TypeLayout.GetMethodParameterStackSize(method) << 16); writer1.Write(value, TypeLayout.NativePointerSize); // 5. Pointer to Method if (!method.IsAbstract) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, method.FullName, SectionKind.Text, 0); } writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 6. Pointer to return type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, method.Signature.ReturnType.FullName + Metadata.TypeDefinition, SectionKind.ROData, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 7. Pointer to Exception Handler Table if (method.ExceptionHandlers.Count != 0) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, method.FullName + Metadata.ProtectedRegionTable, SectionKind.ROData, 0); } writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 8. Pointer to GC Tracking information // TODO: This has yet to be designed. writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 9. Number of Parameters writer1.Write((uint)method.Signature.Parameters.Count, TypeLayout.NativePointerSize); // 10. Pointers to Parameter Definitions foreach (var parameter in method.Signature.Parameters) { // Create definition and get the symbol var parameterDefinitionSymbol = CreateParameterDefinition(parameter); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, parameterDefinitionSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); } // Return methodTableSymbol for linker usage return(methodTableSymbol); }
private void WriteArgument(EndianAwareBinaryWriter writer, LinkerSymbol symbol, MosaType type, object value) { if (type.IsEnum) { type = type.GetEnumUnderlyingType(); } switch (type.TypeCode) { // 1 byte case MosaTypeCode.Boolean: writer.Write((bool)value); break; case MosaTypeCode.U1: writer.Write((byte)value); break; case MosaTypeCode.I1: writer.Write((sbyte)value); break; // 2 bytes case MosaTypeCode.Char: writer.Write((char)value); break; case MosaTypeCode.U2: writer.Write((ushort)value); break; case MosaTypeCode.I2: writer.Write((short)value); break; // 4 bytes case MosaTypeCode.U4: writer.Write((uint)value); break; case MosaTypeCode.I4: writer.Write((int)value); break; case MosaTypeCode.R4: writer.Write((float)value); break; // 8 bytes case MosaTypeCode.U8: writer.Write((ulong)value); break; case MosaTypeCode.I8: writer.Write((long)value); break; case MosaTypeCode.R8: writer.Write((double)value); break; // SZArray case MosaTypeCode.SZArray: Debug.Assert(value is MosaCustomAttribute.Argument[]); var arr = (MosaCustomAttribute.Argument[])value; writer.Write(arr.Length, TypeLayout.NativePointerSize); foreach (var elem in arr) { WriteArgument(writer, symbol, elem.Type, elem.Value); } break; // String case MosaTypeCode.String: // Since strings are immutable, make it an object that we can just use var str = (string)value; Linker.Link(LinkType.AbsoluteAddress, NativePatchType, symbol, writer.Position, Metadata.TypeDefinition + "System.String", 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize * 2); writer.Write(str.Length, TypeLayout.NativePointerSize); writer.Write(System.Text.Encoding.Unicode.GetBytes(str)); break; default: if (type.FullName == "System.Type") { var valueType = (MosaType)value; Linker.Link(LinkType.AbsoluteAddress, NativePatchType, symbol, writer.Position, Metadata.TypeDefinition + valueType.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } else { throw new NotSupportedException(); } break; } }
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 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); }
private LinkerSymbol CreateAssemblyDefinition(MosaModule module) { // Emit assembly name var assemblyNameSymbol = EmitStringWithLength(module.Assembly + Metadata.NameString, module.Assembly); // Emit assembly table var assemblyTableSymbol = Linker.CreateSymbol(module.Assembly + Metadata.AssemblyDefinition, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer1 = new EndianAwareBinaryWriter(assemblyTableSymbol.Stream, Architecture.Endianness); // 1. Pointer to Assembly Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, (int)writer1.Position, 0, assemblyNameSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (module.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(module); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, (int)writer1.Position, 0, customAttributeListSymbol, 0); } writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes - IsReflectionOnly (32bit length) uint flags = 0x0; if (module.IsReflectionOnly) { flags |= 0x1; } writer1.Write(flags, TypeLayout.NativePointerSize); // 4. Number of Types uint count = 0; foreach (var type in module.Types.Values) { if (type.IsModule) { continue; } count++; } writer1.Write(count, TypeLayout.NativePointerSize); // 5. Pointers to Types // Create the definitions along the way foreach (var type in module.Types.Values) { if (type.IsModule) { continue; } // Run the type through the TypeLayout system //TypeLayout.ResolveType(type); var typeTableSymbol = CreateTypeDefinition(type, assemblyTableSymbol); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, (int)writer1.Position, 0, typeTableSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); } // Return assemblyTableSymbol return(assemblyTableSymbol); }
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); }
private LinkerSymbol CreateMethodDefinition(MosaMethod method) { // Emit method name var methodNameSymbol = EmitStringWithLength(Metadata.NameString + method.FullName, method.FullName); // Emit method table var methodTableSymbol = Linker.DefineSymbol(Metadata.MethodDefinition + method.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, (method.Signature.Parameters.Count + 9) * TypeLayout.NativePointerSize); var writer = new EndianAwareBinaryWriter(methodTableSymbol.Stream, Architecture.Endianness); // 1. Pointer to Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, methodNameSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (method.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(method); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, customAttributeListSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes writer.Write((uint)method.MethodAttributes, TypeLayout.NativePointerSize); // 4. Local Stack Size (16 Bits) && Parameter Stack Size (16 Bits) var methodData = Compiler.CompilerData.GetMethodData(method); int value = methodData.LocalMethodStackSize | (methodData.ParameterStackSize << 16); writer.Write(value, TypeLayout.NativePointerSize); // 5. Pointer to Method if (method.HasImplementation && !method.HasOpenGenericParams && !method.DeclaringType.HasOpenGenericParams /*&& !methodData.Inlined*/) // TODO: Inline { if (Compiler.MethodScanner.IsMethodInvoked(method)) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, GetMethodNameConsiderPlug(method), 0); } } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 6. Pointer to return type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, Metadata.TypeDefinition + method.Signature.ReturnType.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 7. Pointer to Exception Handler Table if (method.ExceptionHandlers.Count != 0 && Compiler.MethodScanner.IsMethodInvoked(method)) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, Metadata.ProtectedRegionTable + method.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 8. Pointer to GC Tracking information // TODO: This has yet to be designed. writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 9. Number of Parameters writer.Write((uint)method.Signature.Parameters.Count, TypeLayout.NativePointerSize); // 10. Pointers to Parameter Definitions foreach (var parameter in method.Signature.Parameters) { // Create definition and get the symbol var parameterDefinitionSymbol = CreateParameterDefinition(parameter); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, parameterDefinitionSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } return(methodTableSymbol); }
private LinkerSymbol CreatePropertyDefinitions(MosaType type) { // Emit properties table var propertiesTableSymbol = Linker.CreateSymbol(type.FullName + Metadata.PropertiesTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer1 = new EndianAwareBinaryWriter(propertiesTableSymbol.Stream, Architecture.Endianness); // 1. Number of Properties writer1.Write((uint)type.Properties.Count, TypeLayout.NativePointerSize); // 2. Pointers to Property Definitions foreach (MosaProperty property in type.Properties) { // Emit field name var fieldNameSymbol = EmitStringWithLength(property.FullName + Metadata.NameString, property.Name); // Emit property definition var propertyDefSymbol = Linker.CreateSymbol(property.FullName + Metadata.PropertyDefinition, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer2 = new EndianAwareBinaryWriter(propertyDefSymbol.Stream, Architecture.Endianness); // 1. Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, (int)writer2.Position, 0, 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, (int)writer1.Position, 0, customAttributesTableSymbol, 0); } writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes writer1.Write((uint)property.PropertyAttributes, TypeLayout.NativePointerSize); // 4. Pointer to Property Type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, (int)writer2.Position, 0, property.PropertyType.FullName + Metadata.TypeDefinition, SectionKind.ROData, 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) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, (int)writer2.Position, 0, property.GetterMethod.FullName + Metadata.MethodDefinition, SectionKind.ROData, 0); } writer2.WriteZeroBytes(TypeLayout.NativePointerSize); // 6. Pointer to Setter Method Definition if (property.SetterMethod != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, (int)writer2.Position, 0, property.SetterMethod.FullName + Metadata.MethodDefinition, SectionKind.ROData, 0); } writer2.WriteZeroBytes(TypeLayout.NativePointerSize); } else { // Fill 5 and 6 with zeros. writer1.WriteZeroBytes(TypeLayout.NativePointerSize * 2); } // Add pointer to properties table Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertiesTableSymbol, (int)writer1.Position, 0, propertyDefSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); } // Return fieldListTableSymbol for linker usage return(propertiesTableSymbol); }