Exemple #1
0
        public static void ByReference__ctor(Context context, MethodCompiler methodCompiler)
        {
            var instance   = methodCompiler.Parameters[0];
            var value      = methodCompiler.Parameters[1];
            var opInstance = methodCompiler.AllocateVirtualRegisterOrStackSlot(instance.Type);
            var opValue    = methodCompiler.AllocateVirtualRegisterOrStackSlot(value.Type);

            // Load instance parameter
            var loadInstance = BaseMethodCompilerStage.GetLoadParameterInstruction(instance.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(loadInstance, opInstance, instance);

            // Load value parameter
            var loadValue = BaseMethodCompilerStage.GetLoadParameterInstruction(value.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(loadValue, opValue, value);

            // Store value inside instance
            var store = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Store32 : IRInstruction.Store64;

            context.AppendInstruction(store, null, opInstance, methodCompiler.ConstantZero, opValue);
            context.MosaType = methodCompiler.TypeSystem.BuiltIn.I;

            context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock);
        }
Exemple #2
0
        public static void Unsafe_AddByteOffset(Context context, MethodCompiler methodCompiler)
        {
            var source       = methodCompiler.Parameters[0];
            var byteOffset   = methodCompiler.Parameters[1];
            var opSource     = methodCompiler.AllocateVirtualRegisterOrStackSlot(source.Type);
            var opByteOffset = methodCompiler.AllocateVirtualRegisterOrStackSlot(byteOffset.Type);
            var opReturn     = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType);

            // Load left parameter
            var loadSource = BaseMethodCompilerStage.GetLoadParameterInstruction(source.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(loadSource, opSource, source);

            // Load right parameter
            var loadByteOffset = BaseMethodCompilerStage.GetLoadParameterInstruction(byteOffset.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(loadByteOffset, opByteOffset, byteOffset);

            // Compare and store into result operand
            var add = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Add32 : IRInstruction.Add64;

            context.AppendInstruction(add, opReturn, opSource, opByteOffset);

            // Return comparison result
            var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(setReturn, null, opReturn);

            context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock);
        }
Exemple #3
0
        public static void Unsafe_AreSame(Context context, MethodCompiler methodCompiler)
        {
            var left     = methodCompiler.Parameters[0];
            var right    = methodCompiler.Parameters[1];
            var opLeft   = methodCompiler.AllocateVirtualRegisterOrStackSlot(left.Type);
            var opRight  = methodCompiler.AllocateVirtualRegisterOrStackSlot(right.Type);
            var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType);

            // Load left parameter
            var loadLeft = BaseMethodCompilerStage.GetLoadParameterInstruction(left.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(loadLeft, opLeft, left);

            // Load right parameter
            var loadRight = BaseMethodCompilerStage.GetLoadParameterInstruction(right.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(loadRight, opRight, right);

            // Compare and store into result operand
            context.AppendInstruction(IRInstruction.CompareObject, ConditionCode.Equal, opReturn, opLeft, opRight);

            // Set return
            var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(setReturn, null, opReturn);

            context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock);
        }
Exemple #4
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var zero = Operand.CreateConstant(0, methodCompiler.TypeSystem);
            var size = BaseMethodCompilerStage.GetInstructionSize(context.Size, context.InvokeMethod.Signature.Parameters[1].ParameterType);

            context.SetInstruction(X86.MovStore, size, null, context.Operand1, zero, context.Operand2);
        }
        private static void MovRegToMemory(InstructionNode node, MachineCodeEmitter emitter)
        {
            Debug.Assert(node.Operand3.IsRegister);
            Debug.Assert(node.ResultCount == 0);
            Debug.Assert(!node.Operand3.IsConstant);

            var size          = BaseMethodCompilerStage.GetInstructionSize(node.Size, node.Operand1.Type);
            var linkreference = node.Operand1.IsLabel || node.Operand1.IsField || node.Operand1.IsSymbol;

            // reg to memory       1000 100w: mod reg r/m
            var opcode = new OpcodeEncoder()
                         .AppendConditionalPrefix(0x66, size == InstructionSize.Size16)         // 8:prefix: 16bit
                         .AppendNibble(Bits.b1000)                                              // 4:opcode
                         .Append3Bits(Bits.b100)                                                // 3:opcode
                         .AppendWidthBit(size != InstructionSize.Size8)                         // 1:width
                         .ModRegRMSIBDisplacement(node.Operand3, node.Operand1, node.Operand2)  // Mod-Reg-RM-?SIB-?Displacement
                         .AppendConditionalIntegerValue(0, linkreference);                      // 32:memory

            if (linkreference)
            {
                emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8);
            }
            else
            {
                emitter.Emit(opcode);
            }
        }
 public static void Run(MethodCompiler methodCompiler, BaseMethodCompilerStage stage)
 {
     Run(
         methodCompiler.Trace,
         stage.FormattedStageName,
         methodCompiler.Method,
         methodCompiler.BasicBlocks
         );
 }
 public static void Run(MethodCompiler methodCompiler, BaseMethodCompilerStage stage, NotifyTraceLogHandler handler)
 {
     Run(
         stage.FormattedStageName,
         methodCompiler.Method,
         methodCompiler.BasicBlocks,
         methodCompiler.MethodData.Version,
         handler
         );
 }
Exemple #8
0
        public static void Unsafe_As(Context context, MethodCompiler methodCompiler)
        {
            var source   = methodCompiler.Parameters[0];
            var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType);

            // Load source into return operand
            var loadSource = BaseMethodCompilerStage.GetLoadParameterInstruction(source.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(loadSource, opReturn, source);

            // Set return
            var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(setReturn, null, opReturn);

            context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock);
        }
Exemple #9
0
        public static void Unsafe_SizeOf(Context context, MethodCompiler methodCompiler)
        {
            var type     = methodCompiler.Method.GenericArguments[0];
            var size     = methodCompiler.TypeLayout.GetTypeSize(type);
            var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType);

            // Move constant into return operand
            var move = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64;

            context.AppendInstruction(move, opReturn, methodCompiler.CreateConstant(size));

            // Set return
            var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(setReturn, null, opReturn);

            context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock);
        }
Exemple #10
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentException">@No opcode for operand type. [ + destination + ,  + source + )</exception>
        private OpCode ComputeOpCode(InstructionSize size, Operand destination, Operand source)
        {
            Debug.Assert(destination.IsMemoryAddress);
            Debug.Assert(source.IsRegister || source.IsConstant || source.IsSymbol);

            size = BaseMethodCompilerStage.GetInstructionSize(size, destination);

            if (source.IsSymbol)
            {
                return(RM_C);
            }

            if (source.IsConstant)
            {
                if (size == InstructionSize.Size8)
                {
                    return(RM_C_U8);
                }

                if (size == InstructionSize.Size16)
                {
                    return(M_C_16);
                }

                return(RM_C);
            }

            if (source.IsRegister)
            {
                if (size == InstructionSize.Size8)
                {
                    return(RM_R_U8);
                }

                if (size == InstructionSize.Size16)
                {
                    return(M_R_16);
                }

                return(M_R);
            }

            throw new ArgumentException(@"No opcode for operand type. [" + destination + ", " + source + ")");
        }
        private void CheckAndClearEmptyBlock(BasicBlock block)
        {
            if (block.PreviousBlocks.Count != 0 || block.IsHeadBlock)
            {
                return;
            }

            trace?.Log($"*** Removed Block: {block}");

            var nextBlocks = block.NextBlocks.ToArray();

            EmptyBlockOfAllInstructions(block);

            BaseMethodCompilerStage.RemoveBlocksFromPHIInstructions(block, nextBlocks);

            foreach (var next in nextBlocks)
            {
                CheckAndClearEmptyBlock(next);
            }
        }
Exemple #12
0
        public static void RuntimeHelpers_IsReferenceOrContainsReferences(Context context, MethodCompiler methodCompiler)
        {
            var type     = methodCompiler.Method.GenericArguments[0];
            var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType);

            // FIXME: we're only checking if the current type is a reference type, we aren't checking if it contains references
            var isReferenceOrContainsReferences = type.IsReferenceType;

            // Move constant into return operand
            var move = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64;

            context.AppendInstruction(move, opReturn, methodCompiler.CreateConstant(isReferenceOrContainsReferences ? 1 : 0));

            // Set return
            var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(setReturn, null, opReturn);

            context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock);
        }
Exemple #13
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentException">@No opcode for operand type. [ + destination + ,  + source + )</exception>
        private OpCode ComputeOpCode(InstructionSize size, Operand destination, Operand source)
        {
            Debug.Assert(destination.IsRegister);
            Debug.Assert(source.IsMemoryAddress);

            size = BaseMethodCompilerStage.GetInstructionSize(size, destination);

            Debug.Assert(size != InstructionSize.Size64);

            if (size == InstructionSize.Size8)
            {
                return(R_M_U8);
            }

            if (size == InstructionSize.Size16)
            {
                return(R_RM_16);
            }

            return(R_RM);
        }
Exemple #14
0
        public static void ByReference_get_Value(Context context, MethodCompiler methodCompiler)
        {
            var instance   = methodCompiler.Parameters[0];
            var opInstance = methodCompiler.AllocateVirtualRegisterOrStackSlot(instance.Type);
            var opReturn   = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType);

            // Load instance parameter
            var loadInstance = BaseMethodCompilerStage.GetLoadParameterInstruction(instance.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(loadInstance, opInstance, instance);

            // Load value from instance into return operand
            var loadValue = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Load32 : IRInstruction.Load64;

            context.AppendInstruction(loadValue, opReturn, opInstance, methodCompiler.ConstantZero);
            context.MosaType = methodCompiler.TypeSystem.BuiltIn.I;

            // Set return
            var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(setReturn, null, opReturn);

            context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock);
        }
Exemple #15
0
 public static void RemoveBlockFromPHIInstructions(BasicBlock removedBlock, BasicBlock phiBlock)
 {
     BaseMethodCompilerStage.RemoveBlockFromPHIInstructions(removedBlock, phiBlock);
 }
Exemple #16
0
 public static void UpdatePHIInstructionTargets(List <BasicBlock> targets, BasicBlock source, BasicBlock newSource)
 {
     BaseMethodCompilerStage.UpdatePHIInstructionTargets(targets, source, newSource);
 }
Exemple #17
0
 public static void UpdatePHIInstructionTarget(BasicBlock target, BasicBlock source, BasicBlock newSource)
 {
     BaseMethodCompilerStage.UpdatePHIInstructionTarget(target, source, newSource);
 }
 public static void RemoveBlocksFromPHIInstructions(BasicBlock removedBlock, BasicBlock[] nextBlocks)
 {
     BaseMethodCompilerStage.RemoveBlocksFromPHIInstructions(removedBlock, nextBlocks);
 }