private void AddMoves(BasicBlock block, List <Operand> sourceOperands, List <Operand> destinationOperands)
        {
            var context = new Context(block.Last);

            context.GotoPrevious();

            while (context.IsEmpty ||
                   context.Instruction.FlowControl == FlowControl.ConditionalBranch ||
                   context.Instruction.FlowControl == FlowControl.UnconditionalBranch ||
                   context.Instruction.FlowControl == FlowControl.Return ||
                   context.Instruction == IRInstruction.Jmp)
            {
                context.GotoPrevious();
            }

            for (int i = 0; i < sourceOperands.Count; i++)
            {
                var source      = sourceOperands[i];
                var destination = destinationOperands[i];

                if (MosaTypeLayout.IsStoredOnStack(source.Type))
                {
                    context.AppendInstruction(IRInstruction.MoveCompound, destination, source);
                }
                else
                {
                    var moveInstruction = GetMoveInstruction(source.Type);
                    context.AppendInstruction(moveInstruction, destination, source);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Inserts the copy statement.
        /// </summary>
        /// <param name="predecessor">The predecessor.</param>
        /// <param name="result">The result.</param>
        /// <param name="operand">The operand.</param>
        private void InsertCopyStatement(BasicBlock predecessor, Operand result, Operand operand)
        {
            var context = new Context(predecessor.Last);

            context.GotoPrevious();

            while (context.IsEmpty ||
                   context.Instruction == IRInstruction.CompareIntBranch32 ||
                   context.Instruction == IRInstruction.CompareIntBranch64 ||
                   context.Instruction == IRInstruction.Jmp)
            {
                context.GotoPrevious();
            }

            var source      = operand.IsSSA ? GetFinalVirtualRegister(operand) : operand;
            var destination = result.IsSSA ? GetFinalVirtualRegister(result) : result;

            Debug.Assert(!source.IsSSA);
            Debug.Assert(!destination.IsSSA);

            if (destination != source)
            {
                if (MosaTypeLayout.IsStoredOnStack(destination.Type))
                {
                    context.AppendInstruction(IRInstruction.MoveCompound, destination, source);
                    context.MosaType = destination.Type;
                }
                else
                {
                    var moveInstruction = GetMoveInstruction(destination.Type);
                    context.AppendInstruction(moveInstruction, destination, source);
                }
            }
        }
예제 #3
0
        protected bool CanPromote(Operand operand)
        {
            if (trace.Active)
            {
                trace.Log("Check: " + operand);
            }

            if (operand.Uses.Count == 0)
            {
                if (trace.Active)
                {
                    trace.Log("No uses: " + operand);
                }
                return(false);
            }

            if (MosaTypeLayout.IsStoredOnStack(operand.Type))
            {
                if (trace.Active)
                {
                    trace.Log("incompatible type: " + operand);
                }
                return(false);
            }

            foreach (var node in operand.Uses)
            {
                if (node.Instruction == IRInstruction.AddressOf)
                {
                    Debug.Assert(node.Operand1 == operand);

                    foreach (var node2 in node.Result.Uses)
                    {
                        if (!Check(node2))
                        {
                            return(false);
                        }
                    }
                    continue;
                }
                else if (node.Instruction == IRInstruction.LoadInt32 || node.Instruction == IRInstruction.LoadInt64)
                {
                    Debug.Assert(node.Operand2 == operand);
                    continue;
                }
                else if (node.Instruction == IRInstruction.StoreInt32 || node.Instruction == IRInstruction.StoreInt64)
                {
                    Debug.Assert(node.Operand2 == operand);
                    continue;
                }

                if (trace.Active)
                {
                    trace.Log("A-No: " + node);
                }
                return(false);
            }

            return(true);
        }
예제 #4
0
        private void Push(Context context, Operand operand, int offset, Operand scratch)
        {
            var offsetOperand = CreateConstant(offset);

            if (operand.IsInteger)
            {
                context.AppendInstruction(Select(operand, IRInstruction.StoreInt32, IRInstruction.StoreInt64), null, scratch, offsetOperand, operand);
            }
            else if (operand.IsR4)
            {
                context.AppendInstruction(IRInstruction.StoreFloatR4, null, scratch, offsetOperand, operand);
            }
            else if (operand.IsR8)
            {
                context.AppendInstruction(IRInstruction.StoreFloatR8, null, scratch, offsetOperand, operand);
            }
            else if (MosaTypeLayout.IsStoredOnStack(operand.Type))
            {
                context.AppendInstruction(IRInstruction.StoreCompound, null, scratch, offsetOperand, operand);
            }
            else
            {
                // note: same for integer logic (above)
                context.AppendInstruction(Select(operand, IRInstruction.StoreInt32, IRInstruction.StoreInt64), null, scratch, offsetOperand, operand);
            }
        }
예제 #5
0
        /// <summary>
        /// Inserts the copy statement.
        /// </summary>
        /// <param name="predecessor">The predecessor.</param>
        /// <param name="destination">The result.</param>
        /// <param name="source">The operand.</param>
        private void InsertCopyStatement(BasicBlock predecessor, Operand destination, Operand source)
        {
            if (destination == source)
            {
                return;
            }

            var node = predecessor.BeforeLast;

            while (node.IsEmptyOrNop ||
                   node.Instruction == IRInstruction.CompareIntBranch32 ||
                   node.Instruction == IRInstruction.CompareIntBranch64 ||
                   node.Instruction == IRInstruction.Jmp)
            {
                node = node.Previous;
            }

            var context = new Context(node);

            if (MosaTypeLayout.IsStoredOnStack(destination.Type))
            {
                context.AppendInstruction(IRInstruction.MoveCompound, destination, source);
                context.MosaType = destination.Type;
            }
            else
            {
                var moveInstruction = GetMoveInstruction(destination.Type);
                context.AppendInstruction(moveInstruction, destination, source);
            }
        }
예제 #6
0
        private void SetReturn(Context context)
        {
            var operand = context.Operand1;

            Debug.Assert(operand != null);

            if (operand.IsR4)
            {
                context.SetInstruction(IRInstruction.MoveFloatR4, Operand.CreateCPURegister(operand.Type, Architecture.ReturnFloatingPointRegister), operand);
            }
            else if (operand.IsR8)
            {
                context.SetInstruction(IRInstruction.MoveFloatR8, Operand.CreateCPURegister(operand.Type, Architecture.ReturnFloatingPointRegister), operand);
            }
            else if (operand.IsLong)
            {
                var v1 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);
                var v2 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);

                context.SetInstruction2(IRInstruction.Split64, v1, v2, operand);
                context.AppendInstruction(IRInstruction.MoveInteger, InstructionSize.Size32, Operand.CreateCPURegister(TypeSystem.BuiltIn.U4, Architecture.Return32BitRegister), v1);
                context.AppendInstruction(IRInstruction.MoveInteger, InstructionSize.Size32, Operand.CreateCPURegister(TypeSystem.BuiltIn.U4, Architecture.Return64BitRegister), v2);
            }
            else if (MosaTypeLayout.IsStoredOnStack(operand.Type))
            {
                var OffsetOfFirstParameterOperand = CreateConstant(Architecture.OffsetOfFirstParameter);
                context.SetInstruction(IRInstruction.StoreCompound, null, StackFrame, OffsetOfFirstParameterOperand, operand);
            }
            else
            {
                context.SetInstruction(IRInstruction.MoveInteger, InstructionSize.Size32, Operand.CreateCPURegister(operand.Type, Architecture.Return32BitRegister), operand);
            }
        }
예제 #7
0
        private List <InstructionNode> ScanForNewOperators()
        {
            var list = new List <InstructionNode>();

            foreach (var block in BasicBlocks)
            {
                for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next)
                {
                    if (node.IsEmpty)
                    {
                        continue;
                    }

                    if (node.Instruction is NewobjInstruction)
                    {
                        if (!MosaTypeLayout.IsStoredOnStack(node.Result.Type))
                        {
                            list.Add(node);
                            MethodScanner.TypeAllocated(node.InvokeMethod.DeclaringType, Method);
                        }
                    }
                    else if (node.Instruction is NewarrInstruction)
                    {
                        list.Add(node);
                        MethodScanner.TypeAllocated(node.Result.Type, Method);
                    }
                }
            }

            return(list);
        }
        public bool CanInline(CompilerMethodData method)
        {
            if (method.HasDoNotInlineAttribute)
            {
                return(false);
            }

            if (method.IsMethodImplementationReplaced)
            {
                return(false);
            }

            if (method.HasProtectedRegions)
            {
                return(false);
            }

            //if (method.HasLoops)
            //	return false;

            if (method.IsVirtual && !method.IsDevirtualized)
            {
                return(false);
            }

            // current implementation limitation - can't include methods with addressOf instruction
            if (method.HasAddressOfInstruction)
            {
                return(false);
            }

            if (method.NonIRInstructionCount > 0)
            {
                return(false);
            }

            // methods with aggressive inline attribute will double the IR instruction cout
            int max = !method.HasAggressiveInliningAttribute ? CompilerOptions.InlinedIRMaximum : (CompilerOptions.InlinedIRMaximum * 2);

            if ((method.IRInstructionCount - method.IRStackParameterInstructionCount) > max)
            {
                return(false);
            }

            var returnType = method.Method.Signature.ReturnType;

            // FIXME: Add rational
            if (MosaTypeLayout.IsStoredOnStack(returnType) && !returnType.IsUI8 && !returnType.IsR8)
            {
                return(false);
            }

            return(true);
        }
예제 #9
0
        public bool CanInline(CompilerMethodData method)
        {
            if (method.HasDoNotInlineAttribute)
            {
                return(false);
            }

            if (method.IsPlugged)
            {
                return(false);
            }

            if (method.HasProtectedRegions)
            {
                return(false);
            }

            //if (method.HasLoops)
            //	return false;

            if (method.IsVirtual && !method.IsDevirtualized)
            {
                return(false);
            }

            // current implementation limitation - can't include methods with addressOf instruction
            if (method.HasAddressOfInstruction)
            {
                return(false);
            }

            if (method.NonIRInstructionCount > 0)
            {
                return(false);
            }

            if (method.IRInstructionCount > MethodCompiler.Compiler.CompilerOptions.InlinedIRMaximum)
            {
                return(false);
            }

            var returnType = method.Method.Signature.ReturnType;

            // FIXME: Add rational
            if (MosaTypeLayout.IsStoredOnStack(returnType) && !returnType.IsUI8 && !returnType.IsR8)
            {
                return(false);
            }

            return(true);
        }
예제 #10
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);
        }
예제 #11
0
        private void GetReturnValue(Context context, Operand result)
        {
            if (result == null)
            {
                return;
            }

            if (result.Is64BitInteger && Is32BitPlatform)
            {
                var returnLow  = Operand.CreateCPURegister(result.Type, Architecture.Return32BitRegister);
                var returnHigh = Operand.CreateCPURegister(TypeSystem.BuiltIn.U4, Architecture.Return64BitRegister);

                context.AppendInstruction(IRInstruction.Gen, returnLow);
                context.AppendInstruction(IRInstruction.Gen, returnHigh);
                context.AppendInstruction(IRInstruction.To64, result, returnLow, returnHigh);
            }
            else if (result.IsInteger)
            {
                var returnLow = Operand.CreateCPURegister(result.Type, Architecture.Return32BitRegister);
                context.AppendInstruction(IRInstruction.Gen, returnLow);
                context.AppendInstruction(moveInstruction, result, returnLow);
            }
            else if (result.IsR4)
            {
                var returnFP = Operand.CreateCPURegister(result.Type, Architecture.ReturnFloatingPointRegister);
                context.AppendInstruction(IRInstruction.Gen, returnFP);
                context.AppendInstruction(IRInstruction.MoveFloatR4, result, returnFP);
            }
            else if (result.IsR8)
            {
                var returnFP = Operand.CreateCPURegister(result.Type, Architecture.ReturnFloatingPointRegister);
                context.AppendInstruction(IRInstruction.Gen, returnFP);
                context.AppendInstruction(IRInstruction.MoveFloatR8, result, returnFP);
            }
            else if (MosaTypeLayout.IsStoredOnStack(result.Type))
            {
                Debug.Assert(result.IsStackLocal);
                context.AppendInstruction(IRInstruction.LoadCompound, result, StackPointer, ConstantZero);
            }
            else
            {
                // note: same for integer logic (above)
                var returnLow = Operand.CreateCPURegister(result.Type, Architecture.Return32BitRegister);
                context.AppendInstruction(IRInstruction.Gen, returnLow);
                context.AppendInstruction(moveInstruction, result, returnLow);
            }
        }
예제 #12
0
        public bool StaticCanNotInline(MethodData methodData, MosaMethod method)
        {
            if (methodData.HasDoNotInlineAttribute)
            {
                return(true);
            }

            if (methodData.IsMethodImplementationReplaced)
            {
                return(true);
            }

            if (methodData.HasProtectedRegions)
            {
                return(true);
            }

            if (methodData.IsVirtual && !methodData.IsDevirtualized)
            {
                return(true);
            }

            if (methodData.DoNotInline)
            {
                return(true);
            }

            if (method.DeclaringType.IsValueType &&
                method.IsVirtual &&
                !method.IsConstructor &&
                !method.IsStatic)
            {
                return(true);
            }

            var returnType = methodData.Method.Signature.ReturnType;

            // FIXME: Add rational
            if (MosaTypeLayout.IsStoredOnStack(returnType) && !returnType.IsUI8 && !returnType.IsR8)
            {
                return(true);
            }

            return(false);
        }
예제 #13
0
		private bool StaticCanNotInline(MethodData methodData)
		{
			if (methodData.HasDoNotInlineAttribute)
				return true;

			if (methodData.IsMethodImplementationReplaced)
				return true;

			if (methodData.HasProtectedRegions)
				return true;

			if (methodData.HasMethodPointerReferenced)
				return true;

			var method = methodData.Method;

			if (method.IsVirtual && !methodData.IsDevirtualized)
				return true;

			if (methodData.DoNotInline)
				return true;

			if (method.DeclaringType.IsValueType
				&& method.IsVirtual
				&& !method.IsConstructor
				&& !method.IsStatic)
				return true;

			var returnType = methodData.Method.Signature.ReturnType;

			// FIXME: Add rational
			if (MosaTypeLayout.IsStoredOnStack(returnType) && !returnType.IsUI8 && !returnType.IsR8)
				return true;

			// FUTURE: Don't hardcode namepsace
			if (((method.MethodAttributes & MosaMethodAttributes.Public) == MosaMethodAttributes.Public) && method.DeclaringType.BaseType != null && method.DeclaringType.BaseType.Namespace == "Mosa.UnitTests")
				return true;

			return false;
		}
        private List <InstructionNode> ScanForNewOperators()
        {
            var list = new List <InstructionNode>();

            foreach (var block in BasicBlocks)
            {
                for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next)
                {
                    if (node.IsEmpty)
                    {
                        continue;
                    }

                    if ((node.Instruction is CIL.NewobjInstruction && !MosaTypeLayout.IsStoredOnStack(node.Result.Type)) || node.Instruction is CIL.NewarrInstruction)
                    {
                        list.Add(node);
                    }
                }
            }

            return(list);
        }
        protected BasicBlocks CopyInstructions()
        {
            var newBasicBlocks = new BasicBlocks();
            var mapBlocks      = new Dictionary <BasicBlock, BasicBlock>(BasicBlocks.Count);
            var map            = new Dictionary <Operand, Operand>();

            foreach (var block in BasicBlocks)
            {
                var newBlock = newBasicBlocks.CreateBlock(block.Label);
                mapBlocks.Add(block, newBlock);
            }

            var newPrologueBlock = newBasicBlocks.GetByLabel(BasicBlock.PrologueLabel);

            foreach (var operand in MethodCompiler.Parameters)
            {
                if (operand.Definitions.Count > 0)
                {
                    var newOp = Map(operand, map);

                    var newOperand = Operand.CreateVirtualRegister(operand.Type, -operand.Index);

                    var moveInstruction = MosaTypeLayout.IsStoredOnStack(newOperand.Type)
                                                ? IRInstruction.MoveCompound
                                                : GetMoveInstruction(newOperand.Type);

                    var moveNode = new InstructionNode(moveInstruction, newOperand, newOp);

                    newPrologueBlock.BeforeLast.Insert(moveNode);

                    // redirect map from parameter to virtual register going forward
                    map.Remove(operand);
                    map.Add(operand, newOperand);
                }
            }

            foreach (var block in BasicBlocks)
            {
                var newBlock = newBasicBlocks.GetByLabel(block.Label);

                for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next)
                {
                    if (node.IsEmpty)
                    {
                        continue;
                    }

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount)
                    {
                        ConditionCode = node.ConditionCode
                    };
                    if (node.BranchTargets != null)
                    {
                        // copy targets
                        foreach (var target in node.BranchTargets)
                        {
                            newNode.AddBranchTarget(mapBlocks[target]);
                        }
                    }

                    // copy results
                    for (int i = 0; i < node.ResultCount; i++)
                    {
                        var op    = node.GetResult(i);
                        var newOp = Map(op, map);

                        newNode.SetResult(i, newOp);
                    }

                    // copy operands
                    for (int i = 0; i < node.OperandCount; i++)
                    {
                        var op    = node.GetOperand(i);
                        var newOp = Map(op, map);

                        newNode.SetOperand(i, newOp);
                    }

                    // copy other
                    if (node.MosaType != null)
                    {
                        newNode.MosaType = node.MosaType;
                    }
                    if (node.MosaField != null)
                    {
                        newNode.MosaField = node.MosaField;
                    }

                    newBlock.BeforeLast.Insert(newNode);
                }
            }

            var trace = CreateTraceLog("InlineMap");

            if (trace.Active)
            {
                foreach (var entry in map)
                {
                    trace.Log(entry.Value + " from: " + entry.Key);
                }
            }

            return(newBasicBlocks);
        }