コード例 #1
0
        protected Node Transform(Node node, BasicBlock block, TypeSystem typeSystem, ExpressionVariables variables)
        {
            var newNode = new InstructionNode(node.Instruction, block);

            // todo: determine result type
            // todo: determine size

            int operandIndex = 0;

            foreach (var nodeOperand in node.ParentNodes)
            {
                if (nodeOperand.NodeType == NodeType.Expression)
                {
                    // todo: expressions
                }
                else if (nodeOperand.NodeType == NodeType.FixedIntegerConstant)
                {
                    // todo
                }
                else if (nodeOperand.NodeType == NodeType.FixedDoubleConstant)
                {
                    // todo
                }
                else if (nodeOperand.NodeType == NodeType.ConstantVariable)
                {
                    newNode.SetOperand(operandIndex++, variables.GetOperand(nodeOperand.Alias));
                    continue;
                }
                else if (nodeOperand.NodeType == NodeType.PhyiscalRegister)
                {
                    var type = typeSystem.BuiltIn.I4;                       // todo
                    Operand.CreateCPURegister(type, node.PhysicalRegister);
                    continue;
                }
                else if (nodeOperand.NodeType == NodeType.VirtualRegister)
                {
                    newNode.SetOperand(operandIndex++, variables.GetOperand(nodeOperand.Alias));
                    continue;
                }
                else if (nodeOperand.NodeType == NodeType.OperandVariable)
                {
                    newNode.SetOperand(operandIndex++, variables.GetOperand(nodeOperand.Alias));
                    continue;
                }

                throw new CompilerException("Error");
            }

            return(null);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        private void UpdateNodeWithValueNumbers(InstructionNode node)
        {
            // update operands with their value number
            for (int i = 0; i < node.OperandCount; i++)
            {
                var operand = node.GetOperand(i);

                if (operand.IsVirtualRegister)
                {
                    var valueNumber = GetValueNumber(operand);

                    if (valueNumber != null)
                    {
                        if (operand != valueNumber)
                        {
                            //trace?.Log($"BEFORE: {node}");
                            //trace?.Log($"Replaced: {operand} with {valueNumber}");
                            node.SetOperand(i, valueNumber);

                            trace?.Log($"UPDATED: {node}");
                        }
                    }
                    else
                    {
                        if (IsPhiInstruction(node.Instruction))
                        {
                            continue;
                        }

                        //Debug.Assert(IsPhiInstruction(node.Instruction));

                        if (!IsPhiInstruction(node.Instruction))
                        {
                            throw new CompilerException("ValueNumbering Stage: Expected PHI instruction but found instead: " + node + " for " + operand);
                        }
                    }
                }
            }
        }
コード例 #4
0
        /// <summary>
        /// Emits the constant operands.
        /// </summary>
        /// <param name="node">The node.</param>
        protected void EmitFloatingPointConstants(InstructionNode node)
        {
            for (int i = 0; i < node.OperandCount; i++)
            {
                var operand = node.GetOperand(i);

                if (operand == null || !operand.IsConstant || !operand.IsR)
                {
                    continue;
                }

                if (operand.IsUnresolvedConstant)
                {
                    continue;
                }

                var v1 = AllocateVirtualRegister(operand.Type);

                var symbol = (operand.IsR4) ?
                             MethodCompiler.Linker.GetConstantSymbol(operand.ConstantSingleFloatingPoint)
                                        : MethodCompiler.Linker.GetConstantSymbol(operand.ConstantDoubleFloatingPoint);

                var s1 = Operand.CreateLabel(operand.Type, symbol.Name);

                var before = new Context(node).InsertBefore();

                if (operand.IsR4)
                {
                    before.SetInstruction(X86.MovssLoad, InstructionSize.Size32, v1, s1, ConstantZero);
                }
                else
                {
                    before.SetInstruction(X86.MovsdLoad, InstructionSize.Size64, v1, s1, ConstantZero);
                }

                node.SetOperand(i, v1);
            }
        }
コード例 #5
0
        private void ReplaceOperands(InstructionNode node)
        {
            if (node.Result != null && repl.ContainsKey(node.Result))
            {
                node.Result = repl[node.Result];
            }

            if (node.Result2 != null && repl.ContainsKey(node.Result2))
            {
                node.Result2 = repl[node.Result2];
            }

            int count = node.OperandCount;

            for (int i = 0; i < count; i++)
            {
                var operand = node.GetOperand(i);
                if (operand != null && repl.ContainsKey(operand))
                {
                    node.SetOperand(i, repl[operand]);
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Emits the constant operands.
        /// </summary>
        /// <param name="node">The node.</param>
        protected void EmitFloatingPointConstants(InstructionNode node)
        {
            for (int i = 0; i < node.OperandCount; i++)
            {
                var operand = node.GetOperand(i);

                if (operand == null || !operand.IsConstant || !operand.IsR)
                {
                    continue;
                }

                if (operand.IsUnresolvedConstant)
                {
                    continue;
                }

                var before = new Context(node).InsertBefore();

                var v1 = AllocateVirtualRegister(operand.Type);

                if (operand.IsR4)
                {
                    var symbol = Linker.GetConstantSymbol(operand.ConstantFloat);
                    var label  = Operand.CreateLabel(operand.Type, symbol.Name);
                    before.SetInstruction(MovssLoad, v1, label, ConstantZero);
                }
                else
                {
                    var symbol = Linker.GetConstantSymbol(operand.ConstantDouble);
                    var label  = Operand.CreateLabel(operand.Type, symbol.Name);
                    before.SetInstruction(MovsdLoad, v1, label, ConstantZero);
                }

                node.SetOperand(i, v1);
            }
        }
コード例 #7
0
ファイル: InlineStage.cs プロジェクト: arakis/MOSA-Project
        protected void Inline(InstructionNode callSiteNode, BasicBlocks blocks)
        {
            var mapBlocks = new Dictionary <BasicBlock, BasicBlock>(blocks.Count);
            var map       = new Dictionary <Operand, Operand>();

            var nextBlock = Split(callSiteNode);

            // create basic blocks
            foreach (var block in blocks)
            {
                var newBlock = CreateNewBlock();
                mapBlocks.Add(block, newBlock);
            }

            // copy instructions
            foreach (var block in blocks)
            {
                var newBlock = mapBlocks[block];

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

                    if (node.Instruction == IRInstruction.Prologue)
                    {
                        continue;
                    }

                    if (node.Instruction == IRInstruction.Epilogue)
                    {
                        newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Jmp, nextBlock));
                        continue;
                    }

                    if (node.Instruction == IRInstruction.SetReturn32 ||
                        node.Instruction == IRInstruction.SetReturn64 ||
                        node.Instruction == IRInstruction.SetReturnR4 ||
                        node.Instruction == IRInstruction.SetReturnR8 ||
                        node.Instruction == IRInstruction.SetReturnCompound)
                    {
                        if (callSiteNode.Result != null)
                        {
                            var newOperand = Map(node.Operand1, map, callSiteNode);

                            BaseInstruction moveInstruction = null;

                            if (node.Instruction == IRInstruction.SetReturn32)
                            {
                                moveInstruction = IRInstruction.Move32;
                            }
                            else if (node.Instruction == IRInstruction.SetReturn64)
                            {
                                moveInstruction = IRInstruction.Move64;
                            }
                            else if (node.Instruction == IRInstruction.SetReturnR4)
                            {
                                moveInstruction = IRInstruction.MoveR4;
                            }
                            else if (node.Instruction == IRInstruction.SetReturnR8)
                            {
                                moveInstruction = IRInstruction.MoveR8;
                            }
                            else if (node.Instruction == IRInstruction.SetReturnCompound)
                            {
                                moveInstruction = IRInstruction.MoveCompound;
                            }

                            Debug.Assert(moveInstruction != null);

                            var moveNode = new InstructionNode(moveInstruction, callSiteNode.Result, newOperand);

                            newBlock.BeforeLast.Insert(moveNode);
                        }

                        continue;
                    }

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount)
                    {
                        ConditionCode = node.ConditionCode,
                        Label         = callSiteNode.Label
                    };

                    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, callSiteNode);

                        newNode.SetResult(i, newOp);
                    }

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

                        var newOp = Map(op, map, callSiteNode);

                        newNode.SetOperand(i, newOp);
                    }

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

                    UpdateParameterInstructions(newNode);

                    newBlock.BeforeLast.Insert(newNode);
                }
            }

            var prologue = mapBlocks[blocks.PrologueBlock];

            var callSiteOperands = callSiteNode.GetOperands();

            if (callSiteOperands.Count > 1)
            {
                var context = new Context(prologue);

                for (int i = 1; i < callSiteOperands.Count; i++)
                {
                    var operand = callSiteOperands[i];

                    if (!operand.IsVirtualRegister || operand.Low == null)
                    {
                        continue;
                    }

                    context.AppendInstruction(IRInstruction.GetLow64, operand.Low, operand);
                    context.AppendInstruction(IRInstruction.GetHigh64, operand.High, operand);
                }
            }

            callSiteNode.SetInstruction(IRInstruction.Jmp, prologue);
        }
コード例 #8
0
        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 = StoreOnStack(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.First.Next; !node.IsBlockEndInstruction; node = node.Next)
                {
                    if (node.IsEmpty)
                    {
                        continue;
                    }

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount);
                    newNode.Size          = node.Size;
                    newNode.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;
                    }
                    if (node.InvokeMethod != null)
                    {
                        newNode.InvokeMethod = node.InvokeMethod;
                    }

                    newBlock.BeforeLast.Insert(newNode);
                }
            }

            var trace = CreateTraceLog("InlineMap");

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

            return(newBasicBlocks);
        }
コード例 #9
0
        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);

                    newPrologueBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Move, newOperand, newOp));

                    // 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.First.Next; !node.IsBlockEndInstruction; node = node.Next)
                {
                    if (node.IsEmpty)
                        continue;

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount);
                    newNode.Size = node.Size;
                    newNode.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;
                    if (node.InvokeMethod != null)
                        newNode.InvokeMethod = node.InvokeMethod;

                    newBlock.BeforeLast.Insert(newNode);
                }
            }

            var trace = CreateTraceLog("InlineMap");

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

            return newBasicBlocks;
        }
コード例 #10
0
        protected void Inline(InstructionNode callNode, BasicBlocks blocks)
        {
            var mapBlocks = new Dictionary <BasicBlock, BasicBlock>(blocks.Count);
            var map       = new Dictionary <Operand, Operand>();

            var nextBlock = Split(callNode);

            // create basic blocks
            foreach (var block in blocks)
            {
                var newBlock = CreateNewBlock();
                mapBlocks.Add(block, newBlock);
            }

            // copy instructions
            foreach (var block in blocks)
            {
                var newBlock = mapBlocks[block];

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

                    if (node.Instruction == IRInstruction.Prologue)
                    {
                        continue;
                    }

                    if (node.Instruction == IRInstruction.Epilogue)
                    {
                        continue;
                    }

                    if (node.Instruction == IRInstruction.Return)
                    {
                        if (callNode.Result != null)
                        {
                            var newOp           = Map(node.Operand1, map, callNode);
                            var moveInsturction = GetMoveInstruction(callNode.Result.Type);

                            var moveNode = new InstructionNode(moveInsturction, callNode.Result, newOp);

                            newBlock.BeforeLast.Insert(moveNode);
                        }
                        newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Jmp, nextBlock));

                        continue;
                    }

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount);
                    newNode.Size          = node.Size;
                    newNode.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, callNode);

                        newNode.SetResult(i, newOp);
                    }

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

                        var newOp = Map(op, map, callNode);

                        newNode.SetOperand(i, newOp);
                    }

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

                    UpdateParameterInstructions(newNode);

                    newBlock.BeforeLast.Insert(newNode);
                }
            }

            callNode.SetInstruction(IRInstruction.Jmp, mapBlocks[blocks.PrologueBlock]);
        }
コード例 #11
0
        protected BasicBlocks CopyInstructions()
        {
            var newBasicBlocks = new BasicBlocks();
            var mapBlocks      = new Dictionary <BasicBlock, BasicBlock>(BasicBlocks.Count);
            var map            = new Dictionary <Operand, Operand>();
            var staticCalls    = new List <MosaMethod>();

            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.CanFitInRegister(newOperand)
                                                ? 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.IsEmptyOrNop)
                    {
                        continue;
                    }

                    if (node.Instruction == IRInstruction.CallStatic)
                    {
                        staticCalls.AddIfNew(node.Operand1.Method);
                    }

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount)
                    {
                        ConditionCode = node.ConditionCode,
                        InvokeMethod  = node.InvokeMethod,
                        MosaField     = node.MosaField,
                        MosaType      = node.MosaType,

                        //Label = callSiteNode.Label,
                    };

                    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", 9);

            if (trace != null)
            {
                foreach (var entry in map)
                {
                    trace.Log($"{entry.Value} from: {entry.Key}");
                }
            }

            return(newBasicBlocks);
        }
コード例 #12
0
        private void ReplaceOperands(InstructionNode node)
        {
            if (node.Result != null && repl.ContainsKey(node.Result))
                node.Result = repl[node.Result];

            if (node.Result2 != null && repl.ContainsKey(node.Result2))
                node.Result2 = repl[node.Result2];

            int count = node.OperandCount;
            for (int i = 0; i < count; i++)
            {
                var operand = node.GetOperand(i);
                if (operand != null && repl.ContainsKey(operand))
                    node.SetOperand(i, repl[operand]);
            }
        }
コード例 #13
0
ファイル: InlineStage.cs プロジェクト: yonglehou/MOSA-Project
        protected void Inline(InstructionNode callNode, BasicBlocks blocks)
        {
            var mapBlocks = new Dictionary<BasicBlock, BasicBlock>(blocks.Count);
            var map = new Dictionary<Operand, Operand>();

            var nextBlock = Split(callNode);

            // create basic blocks
            foreach (var block in blocks)
            {
                var newBlock = CreateNewBlock();
                mapBlocks.Add(block, newBlock);
            }

            // copy instructions
            foreach (var block in blocks)
            {
                var newBlock = mapBlocks[block];

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

                    if (node.Instruction == IRInstruction.Prologue)
                        continue;

                    if (node.Instruction == IRInstruction.Epilogue)
                        continue;

                    if (node.Instruction == IRInstruction.Return)
                    {
                        if (callNode.Result != null)
                        {
                            var newOp = Map(node.Operand1, map, callNode);
                            newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Move, callNode.Result, newOp));
                        }
                        newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Jmp, nextBlock));

                        continue;
                    }

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount);
                    newNode.Size = node.Size;
                    newNode.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, callNode);

                        newNode.SetResult(i, newOp);
                    }

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

                        var newOp = Map(op, map, callNode);

                        newNode.SetOperand(i, newOp);
                    }

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

                    newBlock.BeforeLast.Insert(newNode);
                }
            }

            callNode.SetInstruction(IRInstruction.Jmp, mapBlocks[blocks.PrologueBlock]);
        }
コード例 #14
0
        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 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, 0, typeDefinitionSymbol, SectionKind.ROData, 0);
            }

            Operand staticAddress = Operand.CreateManagedSymbol(assignmentField.FieldType, symbolName.Name);
            Operand result1 = MethodCompiler.CreateVirtualRegister(assignmentField.FieldType);

            //Operand result2 = MethodCompiler.CreateVirtualRegister(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 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);
        }