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); } }
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); }
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; } } } }
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); }
protected bool ValidateOperand(InstructionNode node, int operandIndex, ExpressionVariables variables) { if (operandIndex > node.OperandCount) { return(false); } return(ValidateOperand(node.GetOperand(operandIndex), variables)); }
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"); }
/// <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(); }
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"); }
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); }
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); } } } } }
/// <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); } }
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); }
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]); } } }
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"); }
/// <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); } }
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); }
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; } } } } }
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; }
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; } } } }
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); } }