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); } } }
/// <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); } } }
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); }
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); } }
/// <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); } }
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); } }
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); }
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); }
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 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); } }
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); }
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); }