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));
            }
        }
Пример #3
0
        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);
        }
Пример #5
0
        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;
        }
Пример #6
0
        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);
            }
        }
Пример #8
0
        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);
            }
        }
Пример #10
0
        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);
        }
Пример #11
0
        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);
        }
Пример #12
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);
        }
Пример #13
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);
            }
        }
Пример #15
0
 /// <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));
            }
        }
Пример #17
0
        /// <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);
            }
        }
Пример #19
0
        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
                    );
            }
        }
Пример #20
0
        /// <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;
            }
        }
Пример #21
0
        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);
        }
Пример #22
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);
        }
Пример #23
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);
        }
Пример #24
0
 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));
 }