Ejemplo n.º 1
0
        private static void CmpXchg(InstructionNode node, BaseCodeEmitter emitter)
        {
            Debug.Assert(node.Result.IsCPURegister);
            Debug.Assert(node.Operand1.IsCPURegister);
            Debug.Assert(node.Operand2.IsCPURegister);
            Debug.Assert(node.GetOperand(3).IsCPURegister);
            Debug.Assert(node.Result.Register == GeneralPurposeRegister.EAX);
            Debug.Assert(node.Operand1.Register == GeneralPurposeRegister.EAX);
            Debug.Assert(node.ResultCount == 1);

            // Compare EAX with r/m32. If equal, ZF is set and r32 is loaded into r/m32.
            // Else, clear ZF and load r/m32 into EAX.

            // memory, register 0000 1111 : 1011 000w : mod reg r/m
            var opcode = new OpcodeEncoder()
                         .AppendConditionalPrefix(node.Size == InstructionSize.Size16, 0x66)              // 8:prefix: 16bit
                         .AppendNibble(Bits.b0000)                                                        // 4:opcode
                         .AppendNibble(Bits.b1111)                                                        // 4:opcode
                         .AppendNibble(Bits.b1011)                                                        // 4:opcode
                         .Append3Bits(Bits.b000)                                                          // 3:opcode
                         .AppendWidthBit(node.Size != InstructionSize.Size8)                              // 1:width
                         .ModRegRMSIBDisplacement(true, node.GetOperand(3), node.Operand2, node.Operand3) // Mod-Reg-RM-?SIB-?Displacement
                         .AppendConditionalIntegerValue(node.Operand2.IsLinkerResolved, 0);               // 32:memory

            if (node.Operand2.IsLinkerResolved)
            {
                emitter.Emit(opcode, node.Operand2, (opcode.Size - 32) / 8);
            }
            else
            {
                emitter.Emit(opcode);
            }
        }
Ejemplo n.º 2
0
        private bool SimplePhiUpdate(InstructionNode node)
        {
            // Experiment
            var result = node.Result;

            if (result.Definitions.Count != 1)
            {
                return(false);
            }

            for (int i = 0; i < node.OperandCount; i++)
            {
                var operand = node.GetOperand(i);

                if (operand.IsConstant)
                {
                    continue;
                }

                if (operand.Definitions.Count != 1)
                {
                    return(false);
                }

                if (!operand.IsVirtualRegister)
                {
                    return(false);
                }

                if (operand.Definitions[0].Block != node.PhiBlocks[i])
                {
                    return(false);
                }
            }

            for (int i = 0; i < node.OperandCount; i++)
            {
                var operand = node.GetOperand(i);

                if (operand.IsVirtualRegister)
                {
                    operand.Definitions[0].Result = result;

                    ReplaceOperand(operand, result);
                }
                else
                {
                    InsertCopyStatement(node.PhiBlocks[i], result, operand);
                }
            }

            node.Empty();

            return(true);
        }
        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);
        }
Ejemplo n.º 4
0
		private void Phi(InstructionNode node)
		{
			//if (Trace.Active) Trace.Log(node.ToString());

			var result = GetVariableState(node.Result);

			if (result.IsOverDefined)
				return;

			var sourceBlocks = node.PhiBlocks;
			var currentBlock = node.Block;

			//if (Trace.Active) Trace.Log("Loop: " + currentBlock.PreviousBlocks.Count.ToString());

			for (var index = 0; index < currentBlock.PreviousBlocks.Count; index++)
			{
				var predecessor = sourceBlocks[index];

				phiStatements.AddIfNew(predecessor, node);

				bool executable = blockStates[predecessor.Sequence];

				//if (Trace.Active) Trace.Log("# " + index.ToString() + ": " + predecessor.ToString() + " " + (executable ? "Yes" : "No"));

				if (!executable)
					continue;

				if (result.IsOverDefined)
					continue;

				var op = node.GetOperand(index);

				var operand = GetVariableState(op);

				//if (Trace.Active) Trace.Log("# " + index.ToString() + ": " + operand.ToString());

				CheckAndUpdateNullAssignment(result, operand);

				if (operand.IsOverDefined)
				{
					UpdateToOverDefined(result);
					continue;
				}
				else if (operand.IsSingleConstant)
				{
					UpdateToConstant(result, operand.ConstantUnsignedLongInteger);
					continue;
				}
				else if (operand.HasMultipleConstants)
				{
					foreach (var c in operand.Constants)
					{
						UpdateToConstant(result, c);

						if (result.IsOverDefined)
							break;
					}
				}
			}
		}
Ejemplo n.º 5
0
        private Operand Map(Operand operand, Dictionary <Operand, Operand> map, InstructionNode callNode)
        {
            if (operand == null)
            {
                return(null);
            }

            Operand mappedOperand;

            if (map.TryGetValue(operand, out mappedOperand))
            {
                return(mappedOperand);
            }

            if (operand.IsSymbol)
            {
                if (operand.StringData != null)
                {
                    mappedOperand = Operand.CreateStringSymbol(operand.Type.TypeSystem, operand.Name, operand.StringData);
                }
                else if (operand.Method != null)
                {
                    mappedOperand = Operand.CreateSymbolFromMethod(operand.Type.TypeSystem, operand.Method);
                }
                else if (operand.Name != null)
                {
                    mappedOperand = Operand.CreateManagedSymbol(operand.Type, operand.Name);
                }
            }
            else if (operand.IsParameter)
            {
                mappedOperand = callNode.GetOperand(operand.Index + 1);
            }
            else if (operand.IsStackLocal)
            {
                mappedOperand = MethodCompiler.AddStackLocal(operand.Type, operand.IsPinned);
            }
            else if (operand.IsVirtualRegister)
            {
                mappedOperand = AllocateVirtualRegister(operand.Type);
            }
            else if (operand.IsStaticField)
            {
                mappedOperand = Operand.CreateField(operand.Field);
            }
            else if (operand.IsCPURegister)
            {
                mappedOperand = operand;
            }
            else if (operand.IsConstant)
            {
                mappedOperand = operand;
            }

            Debug.Assert(mappedOperand != null);

            map.Add(operand, mappedOperand);

            return(mappedOperand);
        }
Ejemplo n.º 6
0
        protected bool ValidateOperand(InstructionNode node, int operandIndex, ExpressionVariables variables)
        {
            if (operandIndex > node.OperandCount)
            {
                return(false);
            }

            return(ValidateOperand(node.GetOperand(operandIndex), variables));
        }
Ejemplo n.º 7
0
        public override void Emit(InstructionNode node, BaseCodeEmitter emitter)
        {
            System.Diagnostics.Debug.Assert(node.ResultCount == 1);
            System.Diagnostics.Debug.Assert(node.OperandCount == 4);

            if ((node.Operand1.IsCPURegister && node.Operand1.Register.RegisterCode == 0) && node.Operand2.IsCPURegister && node.Operand3.IsConstantZero && node.GetOperand(3).IsCPURegister)
            {
                emitter.OpcodeEncoder.SuppressByte(0x40);
                emitter.OpcodeEncoder.AppendNibble(0b0100);
                emitter.OpcodeEncoder.AppendBit(0b0);
                emitter.OpcodeEncoder.AppendBit((node.GetOperand(3).Register.RegisterCode >> 3) & 0x1);
                emitter.OpcodeEncoder.AppendBit(0b0);
                emitter.OpcodeEncoder.AppendBit((node.Operand2.Register.RegisterCode >> 3) & 0x1);
                emitter.OpcodeEncoder.AppendByte(0x0F);
                emitter.OpcodeEncoder.AppendByte(0xB1);
                emitter.OpcodeEncoder.Append2Bits(0b00);
                emitter.OpcodeEncoder.Append3Bits(node.GetOperand(3).Register.RegisterCode);
                emitter.OpcodeEncoder.Append3Bits(node.Operand2.Register.RegisterCode);
                return;
            }

            throw new Compiler.Common.Exceptions.CompilerException("Invalid Opcode");
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Processes the phi instruction.
        /// </summary>
        /// <param name="node">The context.</param>
        private void ProcessPhiInstruction(InstructionNode node)
        {
            var sourceBlocks = node.PhiBlocks;

            for (var index = 0; index < node.Block.PreviousBlocks.Count; index++)
            {
                var operand     = node.GetOperand(index);
                var predecessor = sourceBlocks[index];

                InsertCopyStatement(predecessor, node.Result, operand);
            }

            node.Empty();
        }
Ejemplo n.º 9
0
        public override void Emit(InstructionNode node, OpcodeEncoder opcodeEncoder)
        {
            System.Diagnostics.Debug.Assert(node.ResultCount == 1);
            System.Diagnostics.Debug.Assert(node.OperandCount == 4);

            if ((node.Operand1.IsCPURegister && node.Operand1.Register.RegisterCode == 0) && node.Operand2.IsCPURegister && node.Operand3.IsConstantZero && node.GetOperand(3).IsCPURegister)
            {
                opcodeEncoder.Append8Bits(0x0F);
                opcodeEncoder.Append8Bits(0xB1);
                opcodeEncoder.Append2Bits(0b00);
                opcodeEncoder.Append3Bits(node.GetOperand(3).Register.RegisterCode);
                opcodeEncoder.Append3Bits(node.Operand2.Register.RegisterCode);
                return;
            }

            throw new Compiler.Common.Exceptions.CompilerException("Invalid Opcode");
        }
Ejemplo n.º 10
0
        public bool Match(InstructionNode node, ExpressionVariables variables)
        {
            if (NodeType == NodeType.Instruction)
            {
                if (!ValidateInstruction(node))
                {
                    return(false);
                }

                for (int i = 0; i < ParentNodes.Count; i++)
                {
                    var parentNode = ParentNodes[i];

                    if (NodeType == NodeType.Any)
                    {
                        continue;
                    }

                    if (parentNode.NodeType == NodeType.Instruction)
                    {
                        var operand = node.GetOperand(i);

                        if (operand.Definitions.Count != 1)
                        {
                            return(false);
                        }

                        var parent = operand.Definitions[0];

                        if (!parentNode.Match(parent, variables))
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        if (!parentNode.ValidateOperand(node, i, variables))
                        {
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }
Ejemplo n.º 11
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);
                        }
                    }
                }
            }
        }
Ejemplo n.º 12
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);
            }
        }
Ejemplo n.º 13
0
        private bool ArePhisRedundant(InstructionNode a, InstructionNode b)
        {
            Debug.Assert(IsPhiInstruction(a.Instruction));
            Debug.Assert(IsPhiInstruction(b.Instruction));

            if (a.OperandCount != b.OperandCount)
            {
                return(false);
            }

            for (int i = 0; i < a.OperandCount; i++)
            {
                var va = a.GetOperand(i);
                var vb = b.GetOperand(i);

                if (va == null || vb == null || va != vb)
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 14
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]);
                }
            }
        }
Ejemplo n.º 15
0
        public override void Emit(InstructionNode node, BaseCodeEmitter emitter)
        {
            System.Diagnostics.Debug.Assert(node.ResultCount == 1);
            System.Diagnostics.Debug.Assert(node.OperandCount == 4);

            if (node.Operand1.IsCPURegister && node.Operand2.IsCPURegister && node.Operand3.IsConstant && node.GetOperand(3).IsConstant)
            {
                emitter.OpcodeEncoder.Append4Bits(GetConditionCode(node.ConditionCode));
                emitter.OpcodeEncoder.Append2Bits(0b00);
                emitter.OpcodeEncoder.Append1Bit(0b0);
                emitter.OpcodeEncoder.Append4Bits(0b0111);
                emitter.OpcodeEncoder.Append1Bit(node.StatusRegister == StatusRegister.Update ? 1 : 0);
                emitter.OpcodeEncoder.Append4Bits(node.Operand1.Register.RegisterCode);
                emitter.OpcodeEncoder.Append4Bits(node.Result.Register.RegisterCode);
                emitter.OpcodeEncoder.Append5BitImmediate(node.Operand3);
                emitter.OpcodeEncoder.Append2BitImmediate(node.GetOperand(3));
                emitter.OpcodeEncoder.Append1Bit(0b0);
                emitter.OpcodeEncoder.Append4Bits(node.Operand2.Register.RegisterCode);
                return;
            }

            throw new Compiler.Common.Exceptions.CompilerException("Invalid Opcode");
        }
Ejemplo n.º 16
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);
            }
        }
Ejemplo n.º 17
0
        public override void Emit(InstructionNode node, OpcodeEncoder opcodeEncoder)
        {
            System.Diagnostics.Debug.Assert(node.ResultCount == 0);
            System.Diagnostics.Debug.Assert(node.OperandCount == 4);

            if (node.Operand1.IsCPURegister && node.Operand2.IsCPURegister && node.Operand3.IsCPURegister && node.GetOperand(3).IsConstant)
            {
                opcodeEncoder.Append4Bits(GetConditionCode(node.ConditionCode));
                opcodeEncoder.Append2Bits(0b00);
                opcodeEncoder.Append1Bit(0b0);
                opcodeEncoder.Append4Bits(0b1000);
                opcodeEncoder.Append1Bit(0b1);
                opcodeEncoder.Append4Bits(node.Operand1.Register.RegisterCode);
                opcodeEncoder.Append4Bits(0b0000);
                opcodeEncoder.Append4Bits(node.Operand3.Register.RegisterCode);
                opcodeEncoder.Append1Bit(0b0);
                opcodeEncoder.Append2BitImmediate(node.GetOperand(3));
                opcodeEncoder.Append1Bit(0b1);
                opcodeEncoder.Append4Bits(node.Operand2.Register.RegisterCode);
                return;
            }

            throw new Compiler.Common.Exceptions.CompilerException("Invalid Opcode");
        }
        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);
        }
Ejemplo n.º 19
0
        private Operand Map(Operand operand, Dictionary <Operand, Operand> map, InstructionNode callSiteNode)
        {
            if (operand == null)
            {
                return(null);
            }

            if (map.TryGetValue(operand, out Operand mappedOperand))
            {
                return(mappedOperand);
            }

            if (operand.IsSymbol)
            {
                if (operand.IsString)
                {
                    // FUTURE: explore operand re-use
                    mappedOperand = Operand.CreateStringSymbol(operand.Name, operand.StringData, operand.Type.TypeSystem);
                }
                else if (operand.Method != null)
                {
                    // FUTURE: explore operand re-use
                    mappedOperand = Operand.CreateSymbolFromMethod(operand.Method, operand.Type.TypeSystem);
                }
                else if (operand.Name != null)
                {
                    // FUTURE: explore operand re-use
                    mappedOperand = Operand.CreateSymbol(operand.Type, operand.Name);
                }
            }
            else if (operand.IsParameter)
            {
                mappedOperand = callSiteNode.GetOperand(operand.Index + 1);
            }
            else if (operand.IsStackLocal)
            {
                mappedOperand = MethodCompiler.AddStackLocal(operand.Type, operand.IsPinned);
            }
            else if (operand.IsVirtualRegister)
            {
                mappedOperand = AllocateVirtualRegister(operand.Type);
            }
            else if (operand.IsStaticField)
            {
                // FUTURE: explore operand re-use
                mappedOperand = Operand.CreateStaticField(operand.Field, TypeSystem);
            }
            else if (operand.IsCPURegister)
            {
                mappedOperand = operand;
            }
            else if (operand.IsConstant)
            {
                mappedOperand = operand;
            }

            Debug.Assert(mappedOperand != null);

            if (operand.HasLongParent)
            {
                MethodCompiler.SplitLongOperand(mappedOperand);

                if (operand.IsLow)
                {
                    mappedOperand = mappedOperand.Low;
                }
                else if (operand.IsHigh)
                {
                    mappedOperand = mappedOperand.High;
                }
            }

            map.Add(operand, mappedOperand);

            return(mappedOperand);
        }
        private void Phi(InstructionNode node)
        {
            MainTrace?.Log(node.ToString());

            var result = GetVariableState(node.Result);

            if (result.IsOverDefined)
            {
                return;
            }

            var sourceBlocks = node.PhiBlocks;
            var currentBlock = node.Block;

            MainTrace?.Log($"Loop: {currentBlock.PreviousBlocks.Count}");

            for (var index = 0; index < currentBlock.PreviousBlocks.Count; index++)
            {
                var predecessor = sourceBlocks[index];

                phiStatements.AddIfNew(predecessor, node);

                bool executable = blockStates[predecessor.Sequence];

                MainTrace?.Log($"# {index}: {predecessor} {(executable ? "Yes" : "No")}");

                if (!executable)
                {
                    continue;
                }

                if (result.IsOverDefined)
                {
                    continue;
                }

                var op = node.GetOperand(index);

                var operand = GetVariableState(op);

                MainTrace?.Log($"# {index}: {operand}");

                CheckAndUpdateNullAssignment(result, operand);

                if (operand.IsOverDefined)
                {
                    UpdateToOverDefined(result);
                    continue;
                }
                else if (operand.IsSingleConstant)
                {
                    UpdateToConstant(result, operand.ConstantUnsignedLongInteger);
                    continue;
                }
                else if (operand.HasMultipleConstants)
                {
                    foreach (var c in operand.Constants)
                    {
                        UpdateToConstant(result, c);

                        if (result.IsOverDefined)
                        {
                            break;
                        }
                    }
                }
            }
        }
Ejemplo n.º 21
0
        private Operand Map(Operand operand, Dictionary<Operand, Operand> map, InstructionNode callNode)
        {
            if (operand == null)
                return null;

            Operand mappedOperand;

            if (map.TryGetValue(operand, out mappedOperand))
            {
                return mappedOperand;
            }

            if (operand.IsSymbol)
            {
                if (operand.StringData != null)
                {
                    mappedOperand = Operand.CreateStringSymbol(operand.Type.TypeSystem, operand.Name, operand.StringData);
                }
                else if (operand.Method != null)
                {
                    mappedOperand = Operand.CreateSymbolFromMethod(operand.Type.TypeSystem, operand.Method);
                }
                else if (operand.Name != null)
                {
                    mappedOperand = Operand.CreateManagedSymbol(operand.Type, operand.Name);
                }
            }
            else if (operand.IsParameter)
            {
                mappedOperand = callNode.GetOperand(operand.Index + 1);
            }
            else if (operand.IsStackLocal)
            {
                mappedOperand = MethodCompiler.StackLayout.AddStackLocal(operand.Type);
            }
            else if (operand.IsVirtualRegister)
            {
                mappedOperand = MethodCompiler.CreateVirtualRegister(operand.Type);
            }
            else if (operand.IsField)
            {
                mappedOperand = Operand.CreateField(operand.Field);
            }
            else if (operand.IsConstant)
            {
                mappedOperand = operand;
            }
            else if (operand.IsCPURegister)
            {
                mappedOperand = operand;
            }

            Debug.Assert(mappedOperand != null);

            map.Add(operand, mappedOperand);

            return mappedOperand;
        }
Ejemplo n.º 22
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]);
            }
        }
        private void Phi(InstructionNode node)
        {
            //if (Trace.Active) Trace.Log(node.ToString());

            var result = GetVariableState(node.Result);

            if (result.IsOverDefined)
                return;

            var sourceBlocks = node.PhiBlocks;

            VariableState first = null;

            var currentBlock = node.Block;

            //if (Trace.Active) Trace.Log("Loop: " + currentBlock.PreviousBlocks.Count.ToString());

            for (var index = 0; index < currentBlock.PreviousBlocks.Count; index++)
            {
                var op = node.GetOperand(index);

                var predecessor = sourceBlocks[index];
                bool executable = blockStates[predecessor.Sequence];

                //if (Trace.Active) Trace.Log("# " + index.ToString() + ": " + predecessor.ToString() + " " + (executable ? "Yes" : "No"));

                phiStatements.AddIfNew(predecessor, node);

                if (!executable)
                    continue;

                var operand = GetVariableState(op);

                //if (Trace.Active) Trace.Log("# " + index.ToString() + ": " + operand.ToString());

                if (operand.IsOverDefined)
                {
                    UpdateToOverDefined(result);
                    return;
                }

                if (operand.IsConstant)
                {
                    if (first == null)
                    {
                        first = operand;
                        continue;
                    }

                    if (!first.AreConstantsEqual(operand))
                    {
                        UpdateToOverDefined(result);
                        return;
                    }
                }
            }

            if (first != null)
            {
                UpdateToConstant(result, first.ConstantUnsignedLongInteger);
            }
        }
        private void Phi(InstructionNode node)
        {
            //if (Trace.Active) Trace.Log(node.ToString());

            var result = GetVariableState(node.Result);

            //UpdateToOverDefined(result); // test

            if (result.IsOverDefined)
                return;

            var sourceBlocks = node.PhiBlocks;
            var currentBlock = node.Block;

            //if (Trace.Active) Trace.Log("Loop: " + currentBlock.PreviousBlocks.Count.ToString());

            for (var index = 0; index < currentBlock.PreviousBlocks.Count; index++)
            {
                var predecessor = sourceBlocks[index];

                phiStatements.AddIfNew(predecessor, node);

                bool executable = blockStates[predecessor.Sequence];

                //if (Trace.Active) Trace.Log("# " + index.ToString() + ": " + predecessor.ToString() + " " + (executable ? "Yes" : "No"));

                if (!executable)
                    continue;

                if (result.IsOverDefined)
                    continue;

                var op = node.GetOperand(index);

                var operand = GetVariableState(op);

                //if (Trace.Active) Trace.Log("# " + index.ToString() + ": " + operand.ToString());

                if (operand.IsOverDefined)
                {
                    UpdateToOverDefined(result);
                    continue;
                }
                else if (operand.IsSingleConstant)
                {
                    UpdateToConstant(result, operand.ConstantUnsignedLongInteger);
                    continue;
                }
                else if (operand.HasMultipleConstants)
                {
                    foreach (var c in operand.Constants)
                    {
                        UpdateToConstant(result, c);

                        if (result.IsOverDefined)
                            break;
                    }
                }
            }
        }
Ejemplo n.º 25
0
        private void Phi(InstructionNode node)
        {
            //if (Trace.Active) Trace.Log(node.ToString());

            var result = GetVariableState(node.Result);

            if (result.IsOverDefined)
            {
                return;
            }

            var sourceBlocks = node.PhiBlocks;

            VariableState first = null;

            var currentBlock = node.Block;

            //if (Trace.Active) Trace.Log("Loop: " + currentBlock.PreviousBlocks.Count.ToString());

            for (var index = 0; index < currentBlock.PreviousBlocks.Count; index++)
            {
                var op = node.GetOperand(index);

                var  predecessor = sourceBlocks[index];
                bool executable  = blockStates[predecessor.Sequence];

                //if (Trace.Active) Trace.Log("# " + index.ToString() + ": " + predecessor.ToString() + " " + (executable ? "Yes" : "No"));

                phiStatements.AddIfNew(predecessor, node);

                if (!executable)
                {
                    continue;
                }

                var operand = GetVariableState(op);

                //if (Trace.Active) Trace.Log("# " + index.ToString() + ": " + operand.ToString());

                if (operand.IsOverDefined)
                {
                    UpdateToOverDefined(result);
                    return;
                }

                if (operand.IsConstant)
                {
                    if (first == null)
                    {
                        first = operand;
                        continue;
                    }

                    if (!first.AreConstantsEqual(operand))
                    {
                        UpdateToOverDefined(result);
                        return;
                    }
                }
            }

            if (first != null)
            {
                UpdateToConstant(result, first.ConstantUnsignedLongInteger);
            }
        }