private void PerformStaticAllocationOf(InstructionNode allocation, InstructionNode assignment) { var allocatedType = (allocation.InvokeMethod != null) ? allocation.InvokeMethod.DeclaringType : allocation.Result.Type; var assignmentField = assignment.MosaField; // Get size of type int typeSize = TypeLayout.GetTypeSize(allocatedType); // If instruction is newarr then get the size of the element, multiply it by array size, and add array header size // Also need to align to a 4-byte boundary if (allocation.Instruction is CIL.NewarrInstruction) { int elements = GetConstant(allocation.Operand1); typeSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * elements) + (TypeLayout.NativePointerSize * 3); } // Allocate a linker symbol to refer to this allocation. Use the destination field name as the linker symbol name. var symbolName = MethodCompiler.Linker.CreateSymbol(assignmentField.FullName + "<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize); // Try to get typeDefinitionSymbol if allocatedType isn't a value type string typeDefinitionSymbol = GetTypeDefinition(allocatedType); if (typeDefinitionSymbol != null) { MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, symbolName, 0, SectionKind.ROData, typeDefinitionSymbol, 0); } var staticAddress = Operand.CreateSymbol(assignmentField.FieldType, symbolName.Name); var result1 = AllocateVirtualRegister(assignmentField.FieldType); //Operand result2 = AllocateVirtualRegister(assignmentField.FieldType); // Issue a load request before the newobj and before the assignment. new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result1, staticAddress); assignment.Operand1 = result1; // If the instruction is a newarr if (allocation.Instruction is CIL.NewarrInstruction) { allocation.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), allocation.Result, result1); return; } //new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result2, staticAddress); // Change the newobj to a call and increase the operand count to include the this ptr. // If the instruction is a newarr, then just replace with a nop instead allocation.Result = null; allocation.ResultCount = 0; allocation.OperandCount++; for (int i = allocation.OperandCount; i > 0; i--) { var op = allocation.GetOperand(i - 1); allocation.SetOperand(i, op); } allocation.Operand1 = result1; allocation.Instruction = CILInstruction.Get(OpCode.Call); }
private void PerformStaticAllocationOf(Context allocation, Context assignment) { MosaType allocatedType = (allocation.InvokeMethod != null) ? allocation.InvokeMethod.DeclaringType : allocation.Result.Type; MosaField assignmentField = (assignment.Instruction is DupInstruction) ? FindStsfldForDup(assignment).MosaField : assignment.MosaField; // Get size of type int typeSize = TypeLayout.GetTypeSize(allocatedType); // If instruction is newarr then get the size of the element, multiply it by array size, and add array header size // Also need to align to a 4-byte boundry if (allocation.Instruction is NewarrInstruction) { typeSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * (int)allocation.Previous.Operand1.ConstantSignedLongInteger) + (TypeLayout.NativePointerSize * 3); } // Allocate a linker symbol to refer to this allocation. Use the destination field name as the linker symbol name. var symbolName = MethodCompiler.Linker.CreateSymbol(assignmentField.FullName + @"<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize); // Try to get typeDefinitionSymbol if allocatedType isn't a value type string typeDefinitionSymbol = GetTypeDefinition(allocatedType); if (typeDefinitionSymbol != null) { MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, BuiltInPatch.I4, symbolName, 0, 0, typeDefinitionSymbol, SectionKind.ROData, 0); } // Issue a load request before the newobj and before the assignment. Operand symbol1 = InsertLoadBeforeInstruction(assignment, symbolName.Name, assignmentField.FieldType); assignment.Operand1 = symbol1; // If the instruction is a newarr and the assignment instruction is a dup then we want to remove it if (allocation.Instruction is NewarrInstruction && assignment.Instruction is DupInstruction) { assignment.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), assignment.Result, assignment.Operand1); } // Change the newobj to a call and increase the operand count to include the this ptr. // If the instruction is a newarr, then just replace with a nop instead allocation.ResultCount = 0; if (allocation.Instruction is NewarrInstruction) { allocation.OperandCount = 0; allocation.SetInstruction(CILInstruction.Get(OpCode.Nop)); } else { Operand symbol2 = InsertLoadBeforeInstruction(allocation, symbolName.Name, assignmentField.FieldType); IEnumerable <Operand> ops = allocation.Operands; allocation.OperandCount++; allocation.Operand1 = symbol2; int i = 0; foreach (Operand op in ops) { i++; allocation.SetOperand(i, op); } allocation.ReplaceInstructionOnly(CILInstruction.Get(OpCode.Call)); } }
private void PerformStaticAllocation(InstructionNode node) { var allocatedType = node.MosaType; // node.Result.Type; //Debug.WriteLine($"Method: {Method} : {node}"); //Debug.WriteLine($" --> {allocatedType}"); MethodScanner.TypeAllocated(allocatedType, Method); int allocationSize; if (node.Instruction == IRInstruction.NewObject) { allocationSize = TypeLayout.GetTypeSize(allocatedType); } else { var elements = (int)GetConstant(node.Operand3); allocationSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * elements) + (TypeLayout.NativePointerSize * 3); } var symbolName = Linker.DefineSymbol(StaticSymbolPrefix + allocatedType.FullName, SectionKind.BSS, Architecture.NativeAlignment, allocationSize); string typeDefinitionSymbol = Metadata.TypeDefinition + allocatedType.FullName; Linker.Link(LinkType.AbsoluteAddress, Is32BitPlatform ? PatchType.I32 : PatchType.I64, symbolName, 0, typeDefinitionSymbol, 0); var staticAddress = Operand.CreateSymbol(allocatedType, symbolName.Name); var move = Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64; node.SetInstruction(move, node.Result, staticAddress); }
/// <summary> /// Lays out all parameters of the method. /// </summary> private void LayoutParameters() { var parameters = new List <Operand>(); int offset = 0; if (MethodCompiler.Method.HasThis || MethodCompiler.Method.HasExplicitThis) { ++offset; } for (int i = 0; i < MethodCompiler.Method.Signature.Parameters.Count + offset; ++i) { var parameter = MethodCompiler.GetParameterOperand(i); parameters.Add(parameter); } int returnSize = 0; if (TypeLayout.IsCompoundType(MethodCompiler.Method.Signature.ReturnType)) { returnSize = TypeLayout.GetTypeSize(MethodCompiler.Method.Signature.ReturnType); } int size = LayoutVariables(parameters, CallingConvention, CallingConvention.OffsetOfFirstParameter + returnSize, false); MethodCompiler.StackLayout.StackParameterSize = size; MethodCompiler.TypeLayout.SetMethodParameterStackSize(MethodCompiler.Method, size); }
private void CalculateMethodParameterSize() { // Check if already computed if (MethodData.ParameterStackSize != 0) { return; } int stacksize = 0; MethodData.ParameterSizes = new List <int>(Method.Signature.Parameters.Count); MethodData.ParameterOffsets = new List <int>(Method.Signature.Parameters.Count); if (Method.HasThis) { stacksize = TypeLayout.NativePointerSize; } foreach (var parameter in Method.Signature.Parameters) { var size = parameter.ParameterType.IsValueType ? TypeLayout.GetTypeSize(parameter.ParameterType) : TypeLayout.NativePointerAlignment; MethodData.ParameterSizes.Add(size); MethodData.ParameterOffsets.Add(stacksize); stacksize += Alignment.AlignUp(size, TypeLayout.NativePointerAlignment); } MethodData.ParameterStackSize = stacksize; }
private void EmitTypes() { writer.WriteLine("[Types]"); writer.WriteLine("TypeID\tTypeDef\tSize\tFullName\tBaseTypeID\tDeclaringTypeID\tElementTypeID"); foreach (var type in TypeSystem.AllTypes) { if (type.IsModule) { continue; } //if (!Linker.IsSymbolDefined(type.FullName)) // continue; writer.WriteLine( "{0}\t{1:x8}\t{2}\t{3}\t{4}\t{5}\t{6}", type.ID, Linker.GetSymbol(type.FullName).VirtualAddress, TypeLayout.GetTypeSize(type), type.FullName, (type.BaseType != null) ? type.BaseType.ID : 0, (type.DeclaringType != null) ? type.DeclaringType.ID : 0, (type.ElementType != null) ? type.ElementType.ID : 0 ); } }
private void CompoundLoad(Context context) { var type = context.Result.Type; int typeSize = TypeLayout.GetTypeSize(type); int alignedTypeSize = typeSize - (typeSize % NativeAlignment); int largeAlignedTypeSize = typeSize - (typeSize % LargeAlignment); Debug.Assert(typeSize > 0, context.Operand2.Name); int offset = 0; if (context.Operand2.IsConstant) { offset = (int)context.Operand2.ConstantSignedLongInteger; } var offsetop = context.Operand2; var src = context.Operand1; var dest = context.Result; Debug.Assert(dest.IsMemoryAddress, dest.Name); var srcReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var dstReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var tmp = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var tmpLarge = Operand.CreateCPURegister(MethodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM1); context.SetInstruction(X86.Nop); context.AppendInstruction(X86.Mov, srcReg, src); context.AppendInstruction(X86.Lea, dstReg, dest); if (!offsetop.IsConstant) { context.AppendInstruction(X86.Add, srcReg, srcReg, offsetop); } for (int i = 0; i < largeAlignedTypeSize; i += LargeAlignment) { // Large Aligned moves allow 128bits to be copied at a time var index = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i); var offset2 = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i + offset); context.AppendInstruction(X86.MovupsLoad, tmpLarge, srcReg, index); context.AppendInstruction(X86.MovupsStore, null, dstReg, index, tmpLarge); } for (int i = largeAlignedTypeSize; i < alignedTypeSize; i += NativeAlignment) { var index = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i); var offset2 = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i + offset); context.AppendInstruction(X86.MovLoad, InstructionSize.Size32, tmp, srcReg, offset2); context.AppendInstruction(X86.MovStore, InstructionSize.Size32, null, dstReg, index, tmp); } for (int i = alignedTypeSize; i < typeSize; i++) { var index = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i); var offset2 = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i + offset); context.AppendInstruction(X86.MovzxLoad, InstructionSize.Size8, tmp, srcReg, offset2); context.AppendInstruction(X86.MovStore, InstructionSize.Size8, null, dstReg, index, tmp); } }
void IIRVisitor.CompoundStore(Context context) { var type = context.Operand3.Type; int typeSize = TypeLayout.GetTypeSize(type); int alignedTypeSize = typeSize - (typeSize % NativeAlignment); int largeAlignedTypeSize = typeSize - (typeSize % LargeAlignment); Debug.Assert(typeSize > 0, MethodCompiler.Method.FullName); int offset = 0; if (context.Operand2.IsConstant) { offset = (int)context.Operand2.ConstantSignedLongInteger; } var offsetop = context.Operand2; var src = context.Operand3; var dest = context.Operand1; Debug.Assert(src.IsMemoryAddress); var srcReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var dstReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var tmp = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var tmpLarge = Operand.CreateCPURegister(MethodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM1); context.SetInstruction(X86.Nop); context.AppendInstruction(X86.Lea, srcReg, src); context.AppendInstruction(X86.Mov, dstReg, dest); if (!offsetop.IsConstant) { context.AppendInstruction(X86.Add, dstReg, dstReg, offsetop); } for (int i = 0; i < largeAlignedTypeSize; i += LargeAlignment) { // Large Aligned moves allow 128bits to be copied at a time var memSrc = Operand.CreateMemoryAddress(MethodCompiler.TypeSystem.BuiltIn.Void, srcReg, i); var memDest = Operand.CreateMemoryAddress(MethodCompiler.TypeSystem.BuiltIn.Void, dstReg, i + offset); context.AppendInstruction(X86.MovAPS, InstructionSize.Size128, tmpLarge, memSrc); context.AppendInstruction(X86.MovAPS, InstructionSize.Size128, memDest, tmpLarge); } for (int i = largeAlignedTypeSize; i < alignedTypeSize; i += NativeAlignment) { context.AppendInstruction(X86.Mov, InstructionSize.Size32, tmp, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, srcReg, i)); context.AppendInstruction(X86.Mov, InstructionSize.Size32, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, dstReg, i + offset), tmp); } for (int i = alignedTypeSize; i < typeSize; i++) { context.AppendInstruction(X86.Mov, InstructionSize.Size8, tmp, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, srcReg, i)); context.AppendInstruction(X86.Mov, InstructionSize.Size8, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, dstReg, i + offset), tmp); } }
private void CompoundMove(Context context) { var type = context.Result.Type; int typeSize = TypeLayout.GetTypeSize(type); int alignedTypeSize = typeSize - (typeSize % NativeAlignment); int largeAlignedTypeSize = typeSize - (typeSize % LargeAlignment); Debug.Assert(typeSize > 0, MethodCompiler.Method.FullName); var src = context.Operand1; var dest = context.Result; Debug.Assert((src.IsMemoryAddress || src.IsSymbol) && dest.IsMemoryAddress, context.ToString()); var srcReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var dstReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var tmp = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var tmpLarge = Operand.CreateCPURegister(MethodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM1); context.SetInstruction(X86.Nop); if (src.IsSymbol) { context.AppendInstruction(X86.Mov, srcReg, src); } else { context.AppendInstruction(X86.Lea, srcReg, src); } context.AppendInstruction(X86.Lea, dstReg, dest); for (int i = 0; i < largeAlignedTypeSize; i += LargeAlignment) { // Large Aligned moves allow 128bits to be copied at a time var index = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i); context.AppendInstruction(X86.MovupsLoad, tmpLarge, srcReg, index); context.AppendInstruction(X86.MovupsStore, null, dstReg, index, tmpLarge); } for (int i = largeAlignedTypeSize; i < alignedTypeSize; i += NativeAlignment) { var index = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i); context.AppendInstruction(X86.MovLoad, InstructionSize.Size32, tmp, srcReg, index); context.AppendInstruction(X86.MovStore, InstructionSize.Size32, null, dstReg, index, tmp); } for (int i = alignedTypeSize; i < typeSize; i++) { var index = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i); context.AppendInstruction(X86.MovzxLoad, InstructionSize.Size8, tmp, srcReg, index); context.AppendInstruction(X86.MovStore, InstructionSize.Size8, null, dstReg, index, tmp); } }
private void LayoutParameters() { int returnSize = 0; if (StoreOnStack(Method.Signature.ReturnType)) { returnSize = TypeLayout.GetTypeSize(Method.Signature.ReturnType); } int size = LayoutParameters(Architecture.CallingConvention.OffsetOfFirstParameter + returnSize); StackParameterSize = size; TypeLayout.SetMethodParameterStackSize(Method, size); }
private int CalculateReturnSize(Operand result) { if (result == null) { return(0); } var returnType = result.Type; if (MosaTypeLayout.IsStoredOnStack(returnType)) { return(Alignment.AlignUp(TypeLayout.GetTypeSize(returnType), NativeAlignment)); } return(0); }
private int CalculateReturnSize(Operand result) { if (result == null) { return(0); } var returnType = result.Type; if (!MosaTypeLayout.CanFitInRegister(returnType)) { return(Alignment.AlignUp(TypeLayout.GetTypeSize(returnType), NativeAlignment)); } return(0); }
private void CalculateMethodParameterSize() { int stacksize = 0; if (Method.HasThis) { stacksize = TypeLayout.NativePointerSize; } foreach (var parameter in Method.Signature.Parameters) { var size = parameter.ParameterType.IsValueType ? TypeLayout.GetTypeSize(parameter.ParameterType) : TypeLayout.NativePointerAlignment; stacksize += Alignment.AlignUp(size, TypeLayout.NativePointerAlignment); } MethodData.ParameterStackSize = stacksize; }
void IIRVisitor.CompoundStore(Context context) { var type = context.Operand3.Type; int typeSize = TypeLayout.GetTypeSize(type); int alignedTypeSize = typeSize - (typeSize % NativeAlignment); Debug.Assert(typeSize > 0, MethodCompiler.Method.FullName); int offset = 0; if (context.Operand2.IsConstant) { offset = (int)context.Operand2.ConstantSignedLongInteger; } var offsetop = context.Operand2; var src = context.Operand3; var dest = context.Operand1; Debug.Assert(src.IsMemoryAddress); var srcReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var dstReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var tmp = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); context.SetInstruction(X86.Nop); context.AppendInstruction(X86.Lea, srcReg, src); context.AppendInstruction(X86.Mov, dstReg, dest); if (!offsetop.IsConstant) { context.AppendInstruction(X86.Add, dstReg, dstReg, offsetop); } for (int i = 0; i < alignedTypeSize; i += NativeAlignment) { context.AppendInstruction(X86.Mov, InstructionSize.Size32, tmp, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, srcReg, i)); context.AppendInstruction(X86.Mov, InstructionSize.Size32, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, dstReg, i + offset), tmp); } for (int i = alignedTypeSize; i < typeSize; i++) { context.AppendInstruction(X86.Mov, InstructionSize.Size8, tmp, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, srcReg, i)); context.AppendInstruction(X86.Mov, InstructionSize.Size8, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, dstReg, i + offset), tmp); } }
/// <summary> /// Gets the size of the reference or type. /// </summary> /// <param name="type">The type.</param> /// <param name="aligned">if set to <c>true</c> [aligned].</param> /// <returns></returns> public int GetReferenceOrTypeSize(MosaType type, bool aligned) { if (type.IsValueType) { if (aligned) { return(Alignment.AlignUp(TypeLayout.GetTypeSize(type), Architecture.NativeAlignment)); } else { return(TypeLayout.GetTypeSize(type)); } } else { return(Architecture.NativeAlignment); } }
private void PerformStaticAllocation(Context context) { var allocatedType = context.MosaType; // node.Result.Type; var handle = context.Operand1; bool newObject = context.Instruction == IRInstruction.NewObject; int elements = 0; //Debug.WriteLine($"Method: {Method} : {node}"); //Debug.WriteLine($" --> {allocatedType}"); MethodScanner.TypeAllocated(allocatedType, Method); int allocationSize; if (newObject) { allocationSize = TypeLayout.GetTypeSize(allocatedType); } else { elements = (int)GetConstant(context.Operand3); allocationSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * elements) + (TypeLayout.NativePointerSize * 3); } var symbolName = Linker.DefineSymbol(StaticSymbolPrefix + allocatedType.FullName, SectionKind.BSS, Architecture.NativeAlignment, allocationSize); string typeDefinitionSymbol = Metadata.TypeDefinition + allocatedType.FullName; Linker.Link(LinkType.AbsoluteAddress, Is32BitPlatform ? PatchType.I32 : PatchType.I64, symbolName, 0, typeDefinitionSymbol, 0); var staticAddress = Operand.CreateSymbol(allocatedType, symbolName.Name); var move = Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64; var store = Is32BitPlatform ? (BaseInstruction)IRInstruction.Store32 : IRInstruction.Store64; context.SetInstruction(move, context.Result, staticAddress); context.AppendInstruction(store, null, staticAddress, ConstantZero, handle); if (!newObject) { context.AppendInstruction(store, null, staticAddress, CreateConstant32(2 * (Is32BitPlatform ? 4 : 8)), CreateConstant32(elements)); } }
/// <summary> /// Evaluates the parameter operands. /// </summary> private void EvaluateParameterOperands() { int offset = Architecture.OffsetOfFirstParameter; //offset += MethodData.ReturnInRegister ? MethodData.ReturnSize : 0; if (!MosaTypeLayout.CanFitInRegister(Method.Signature.ReturnType)) { offset += TypeLayout.GetTypeSize(Method.Signature.ReturnType); } //Debug.Assert((MethodData.ReturnInRegister ? MethodData.ReturnSize : 0) == TypeLayout.GetTypeSize(Method.Signature.ReturnType)); int index = 0; if (Method.HasThis || Method.HasExplicitThis) { if (Method.DeclaringType.IsValueType) { var ptr = Method.DeclaringType.ToManagedPointer(); SetStackParameter(index++, ptr, "this", true, offset); var size = GetReferenceOrTypeSize(ptr, true); offset += size; } else { SetStackParameter(index++, Method.DeclaringType, "this", true, offset); var size = GetReferenceOrTypeSize(Method.DeclaringType, true); offset += size; } } foreach (var parameter in Method.Signature.Parameters) { SetStackParameter(index++, parameter.ParameterType, parameter.Name, false, offset); var size = GetReferenceOrTypeSize(parameter.ParameterType, true); offset += size; } }
void IIRVisitor.CompoundMove(Context context) { var type = context.Result.Type; int typeSize = TypeLayout.GetTypeSize(type); int alignedTypeSize = typeSize - (typeSize % NativeAlignment); Debug.Assert(typeSize > 0, MethodCompiler.Method.FullName); var src = context.Operand1; var dest = context.Result; Debug.Assert((src.IsMemoryAddress || src.IsSymbol) && dest.IsMemoryAddress, context.ToString()); var srcReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var dstReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var tmp = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); context.SetInstruction(X86.Nop); if (src.IsSymbol) { context.AppendInstruction(X86.Mov, srcReg, src); } else { context.AppendInstruction(X86.Lea, srcReg, src); } context.AppendInstruction(X86.Lea, dstReg, dest); for (int i = 0; i < alignedTypeSize; i += NativeAlignment) { context.AppendInstruction(X86.Mov, InstructionSize.Size32, tmp, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, srcReg, i)); context.AppendInstruction(X86.Mov, InstructionSize.Size32, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, dstReg, i), tmp); } for (int i = alignedTypeSize; i < typeSize; i++) { context.AppendInstruction(X86.Mov, InstructionSize.Size8, tmp, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, srcReg, i)); context.AppendInstruction(X86.Mov, InstructionSize.Size8, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, dstReg, i), tmp); } }
private void EmitTypes() { writer.WriteLine("[Types]"); writer.WriteLine("TypeDef\tSize\tFullName\tParent Type\tDeclaring Type\tElement Type"); foreach (var type in TypeSystem.AllTypes) { if (type.IsModule) { continue; } writer.WriteLine( "{0:x8}\t{1}\t{2}\t{3}\t{4}\t{5}", Linker.GetSymbol(type.FullName + Metadata.TypeDefinition, SectionKind.ROData).VirtualAddress, TypeLayout.GetTypeSize(type), type.FullName, (type.BaseType != null) ? type.BaseType.FullName : string.Empty, (type.DeclaringType != null) ? type.DeclaringType.FullName : string.Empty, (type.ElementType != null) ? type.ElementType.FullName : string.Empty ); } }
/// <summary> /// Evaluates the parameter operands. /// </summary> private void EvaluateParameterOperands() { int offset = Architecture.OffsetOfFirstParameter; if (MosaTypeLayout.IsStoredOnStack(Method.Signature.ReturnType)) { offset += TypeLayout.GetTypeSize(Method.Signature.ReturnType); } int index = 0; if (Method.HasThis || Method.HasExplicitThis) { if (Type.IsValueType) { var ptr = Type.ToManagedPointer(); SetStackParameter(index++, ptr, "this", true, offset); var size = GetReferenceOrTypeSize(ptr, true); offset += size; } else { SetStackParameter(index++, Type, "this", true, offset); var size = GetReferenceOrTypeSize(Type, true); offset += size; } } foreach (var parameter in Method.Signature.Parameters) { SetStackParameter(index++, parameter.ParameterType, parameter.Name, false, offset); var size = GetReferenceOrTypeSize(parameter.ParameterType, true); offset += size; } }
private void CopyCompound(Context context, MosaType type, Operand destinationBase, Operand destination, Operand sourceBase, Operand source) { int size = TypeLayout.GetTypeSize(type); Debug.Assert(size > 0); var addInstruction = Is32BitPlatform ? (BaseInstruction)IRInstruction.Add32 : IRInstruction.Add64; var srcReg = Is32BitPlatform ? AllocateVirtualRegister32() : AllocateVirtualRegister64(); var dstReg = Is32BitPlatform ? AllocateVirtualRegister32() : AllocateVirtualRegister64(); context.SetInstruction(IRInstruction.UnstableObjectTracking); context.AppendInstruction(addInstruction, srcReg, sourceBase, source); context.AppendInstruction(addInstruction, dstReg, destinationBase, destination); var tmp = AllocateVirtualRegister32(); var tmpLarge = Is32BitPlatform && size >= 8 ? null : AllocateVirtualRegister64(); for (int i = 0; i < size;) { int left = size - i; var index = CreateConstant32(i); if (left >= 8 & !Is32BitPlatform) { // 64bit move context.AppendInstruction(IRInstruction.Load64, tmpLarge, srcReg, index); context.AppendInstruction(IRInstruction.Store64, null, dstReg, index, tmpLarge); i += 8; continue; } else if (left >= 4) { // 32bit move context.AppendInstruction(IRInstruction.Load32, tmp, srcReg, index); context.AppendInstruction(IRInstruction.Store32, null, dstReg, index, tmp); i += 4; continue; } else if (left >= 2) { // 16bit move context.AppendInstruction(IRInstruction.LoadParamZeroExtend16x32, tmp, srcReg, index); context.AppendInstruction(IRInstruction.Store16, null, dstReg, index, tmp); i += 2; continue; } else { // 8bit move context.AppendInstruction(IRInstruction.LoadParamZeroExtend8x32, tmp, srcReg, index); context.AppendInstruction(IRInstruction.Store8, null, dstReg, index, tmp); i += 1; continue; } } context.AppendInstruction(IRInstruction.StableObjectTracking); }
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); }
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); }
private void CopyCompound(Context context, MosaType type, Operand destinationBase, Operand destination, Operand sourceBase, Operand source) { context.Empty(); Architecture.InsertCompoundCopy(MethodCompiler, context, destinationBase, destination, sourceBase, source, TypeLayout.GetTypeSize(type)); }