示例#1
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
        public override StatementList ReadInstanceField(InstanceFieldAccess instanceFieldAccess, IVariable result)
        {
            StatementList stmts      = new StatementList();
            var           boogieType = Helpers.GetBoogieType(result);

            var readFieldExpr = dispatcher.ReadInstanceField(instanceFieldAccess);

            if (!Settings.SplitFieldsEnabled())
            {
                if (!Helpers.IsBoogieRefType(Helpers.GetBoogieType(result))) // int, bool, real
                {
                    var expr = Expression.Union2PrimitiveType(boogieType, readFieldExpr);
                    stmts.Add(bg.VariableAssignment(result, expr));
                }
                else
                {
                    stmts.Add(bg.VariableAssignment(result, readFieldExpr));
                }
            }
            else
            {
                //p_int:= F$ConsoleApplication3.Holds`1.x[$tmp2];
                if (Helpers.IsGenericField(instanceFieldAccess.Field) &&
                    !boogieType.Equals(Helpers.BoogieType.Ref))
                {
                    stmts.Add(bg.VariableAssignment(result, Expression.Union2PrimitiveType(boogieType, readFieldExpr)));
                }
                else
                {
                    stmts.Add(bg.VariableAssignment(result, readFieldExpr));
                }
            }

            return(stmts);
        }
示例#2
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
        public override Expression ReadInstanceField(InstanceFieldAccess instanceFieldAccess)
        {
            var fieldAddr = dispatcher.AddressOf(instanceFieldAccess);
            var readValue = dispatcher.ReadAddr(fieldAddr);

            return(readValue);
        }
示例#3
0
        private void ProcessLoad(PointsToGraph ptg, uint offset, IVariable dst, InstanceFieldAccess access)
        {
            if (dst.Type.IsValueType || access.Type.IsValueType)
            {
                return;
            }

            ptg.RemoveEdges(dst);
            var nodes = ptg.GetTargets(access.Instance);

            foreach (var node in nodes)
            {
                var hasField = node.Targets.ContainsKey(access.Field);

                if (!hasField)
                {
                    var target = this.GetNode(ptg, offset, dst.Type, PTGNodeKind.Unknown);

                    ptg.PointsTo(node, access.Field, target);
                }

                var targets = node.Targets[access.Field];

                foreach (var target in targets)
                {
                    ptg.PointsTo(dst, target);
                }
            }
        }
示例#4
0
        public static bool MayAlias(this PointsToGraph ptg, InstanceFieldAccess access1, InstanceFieldAccess access2)
        {
            var targets1 = ptg.GetTargets(access1);
            var targets2 = ptg.GetTargets(access2);
            var alias    = targets1.Intersect(targets2);

            return(alias.Any());
        }
示例#5
0
        public static bool MayAlias(this PointsToGraph ptg, InstanceFieldAccess access, IVariable variable)
        {
            var targetsAccess   = ptg.GetTargets(access);
            var targetsVariable = ptg.GetTargets(variable);
            var alias           = targetsAccess.Intersect(targetsVariable);

            return(alias.Any());
        }
示例#6
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
 public override StatementList WriteInstanceField(InstanceFieldAccess instanceFieldAccess, Expression value, InstructionTranslator instTranslator)
 {
     if (RequiresAllocation(instanceFieldAccess))
     {
         return(memAddr.WriteInstanceField(instanceFieldAccess, value, instTranslator));
     }
     else
     {
         return(memBCT.WriteInstanceField(instanceFieldAccess, value, instTranslator));
     }
 }
示例#7
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
 public override Expression ReadInstanceField(InstanceFieldAccess instanceFieldAccess)
 {
     if (RequiresAllocation(instanceFieldAccess))
     {
         return(memAddr.ReadInstanceField(instanceFieldAccess));
     }
     else
     {
         return(memBCT.ReadInstanceField(instanceFieldAccess));
     }
 }
示例#8
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
 public override Addressable AddressOf(InstanceFieldAccess instanceFieldAccess)
 {
     if (RequiresAllocation(instanceFieldAccess) || instanceFieldAccess.Type is IManagedPointerType)
     {
         return(memAddr.AddressOf(instanceFieldAccess));
     }
     else
     {
         return(memBCT.AddressOf(instanceFieldAccess));
     }
 }
示例#9
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
 public override Expression ReadInstanceField(InstanceFieldAccess instanceFieldAccess)
 {
     if (!Settings.SplitFieldsEnabled())
     {
         return(ReadFieldExpression.From(new InstanceField(instanceFieldAccess)));
     }
     else
     {
         return(dispatcher.ReadAddr(dispatcher.AddressOf(instanceFieldAccess)));
     }
 }
示例#10
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
        public override StatementList ReadInstanceField(InstanceFieldAccess instanceFieldAccess, IVariable result)
        {
            // with split fields false, i guess we should cast to union always
            Contract.Assert(Settings.SplitFieldsEnabled());

            Expression readExpr = ReadInstanceField(instanceFieldAccess);

            if (Helpers.IsGenericField(instanceFieldAccess.Field))
            {
                if (!Helpers.IsBoogieRefType(result))
                {
                    var boogieType = Helpers.GetBoogieType(result);
                    return(bg.VariableAssignment(result, Expression.Union2PrimitiveType(boogieType, readExpr)));
                }
            }

            return(bg.VariableAssignment(result, readExpr));
        }
示例#11
0
        private void ProcessStore(PointsToGraph ptg, InstanceFieldAccess access, IVariable src)
        {
            if (access.Type.IsValueType || src.Type.IsValueType)
            {
                return;
            }

            var nodes   = ptg.GetTargets(access.Instance);
            var targets = ptg.GetTargets(src);

            foreach (var node in nodes)
            {
                foreach (var target in targets)
                {
                    ptg.PointsTo(node, access.Field, target);
                }
            }
        }
示例#12
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
        public override StatementList WriteInstanceField(InstanceFieldAccess instanceFieldAccess, Expression expr, InstructionTranslator instTranslator)
        {
            StatementList stmts = new StatementList();

            var boogieType = expr.Type;

            if (Helpers.IsGenericField(instanceFieldAccess.Field) && !boogieType.Equals(Helpers.BoogieType.Object))
            {
                stmts.Add(Expression.AssumeInverseRelationUnionAndPrimitiveType(expr));
                stmts.Add(dispatcher.WriteAddr(dispatcher.AddressOf(instanceFieldAccess), Expression.PrimitiveType2Union(expr, instTranslator.Boogie())));
            }
            else
            {
                stmts.Add(dispatcher.WriteAddr(dispatcher.AddressOf(instanceFieldAccess), expr));
            }

            return(stmts);
        }
示例#13
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
        public override StatementList WriteInstanceField(InstanceFieldAccess instanceFieldAccess, Expression expr, InstructionTranslator instTranslator)
        {
            StatementList stmts = new StatementList();

            String fieldName = FieldTranslator.GetFieldName(instanceFieldAccess.Field);

            //var addr = AddressOf(instanceFieldAccess);
            //var writeAddr = WriteAddr(addr, value);

            if (!Settings.SplitFieldsEnabled())
            {
                if (!Helpers.IsBoogieRefType(expr.Type)) // int, bool, real
                {
                    stmts.Add(Expression.AssumeInverseRelationUnionAndPrimitiveType(expr));
                    stmts.Add(dispatcher.WriteAddr(dispatcher.AddressOf(instanceFieldAccess), Expression.PrimitiveType2Union(expr, instTranslator.Boogie())));
                    //sb.AppendLine(String.Format("\t\t$Heap := Write($Heap, {0}, {1}, {2});", instanceFieldAccess.Instance, fieldName, PrimitiveType2Union(Helpers.GetBoogieType(value.Type), value.Name)));
                }
                else
                {
                    stmts.Add(dispatcher.WriteAddr(dispatcher.AddressOf(instanceFieldAccess), expr));
                    //sb.AppendLine(String.Format("\t\t$Heap := Write($Heap, {0}, {1}, {2});", instanceFieldAccess.Instance, fieldName, value.Name));
                }
            }
            else
            {
                var boogieType = expr.Type;
                // var heapAccess = String.Format("{0}[{1}]", fieldName, instanceFieldAccess.Instance);
                //F$ConsoleApplication3.Foo.p[f_Ref] := $ArrayContents[args][0];

                if (Helpers.IsGenericField(instanceFieldAccess.Field) && !boogieType.Equals(Helpers.BoogieType.Ref))
                {
                    stmts.Add(Expression.AssumeInverseRelationUnionAndPrimitiveType(expr));
                    //sb.AppendLine(VariableAssignment(heapAccess, PrimitiveType2Union(boogieType, value.Name)));
                    stmts.Add(dispatcher.WriteAddr(dispatcher.AddressOf(instanceFieldAccess), Expression.PrimitiveType2Union(expr, instTranslator.Boogie())));
                }
                else
                {
                    stmts.Add(dispatcher.WriteAddr(dispatcher.AddressOf(instanceFieldAccess), expr));
                }
            }

            return(stmts);
        }
示例#14
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
        public override StatementList ReadInstanceField(InstanceFieldAccess instanceFieldAccess, IVariable result)
        {
            var readValue = dispatcher.ReadInstanceField(instanceFieldAccess);

            // dependiendo del type (del result?) indexo en el $memoryInt
            if (Helpers.IsGenericField(instanceFieldAccess.Field))
            {
                var boogieType = Helpers.GetBoogieType(result);
                if (!boogieType.Equals(Helpers.BoogieType.Object))
                {
                    return(bg.VariableAssignment(result, Expression.Union2PrimitiveType(boogieType, readValue)));
                }
                else
                {
                    return(bg.VariableAssignment(result, readValue));
                }
            }
            else
            {
                return(bg.VariableAssignment(result, readValue));
            }
        }
示例#15
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
 public abstract StatementList ReadInstanceField(InstanceFieldAccess instanceFieldAccess, IVariable result);
示例#16
0
        // some field initialization can be missing in constructors
        // example:

        /*
         * class Foo{
         *      int x; // this initialization is not added by the compiler
         *      int y = y;
         *  }
         */

        // therefore we are adding the initialization for each field at the top of every constructor.

        public void Transform()
        {
            // these variables hold the default value
            IDictionary <Helpers.BoogieType, LocalVariable> boogieTypeToLocalVariable =
                new Dictionary <Helpers.BoogieType, LocalVariable>();

            // they are the same stored in boogieTypeToLocalVariable
            IList <LocalVariable> variables
                = new List <LocalVariable>();

            // assignment of constants
            IList <Instruction> instructions
                = new List <Instruction>();

            CreateLocalVariablesWithDefaultValues(boogieTypeToLocalVariable, variables, instructions);

            // we need to initialize local variables.

            foreach (var lv in methodBody.Variables)
            {
                if (lv.IsParameter ||
                    // in the delegate handling this type of variables are not used
                    // calling get boogie type will crash
                    lv.Type is Microsoft.Cci.Immutable.FunctionPointerType ||
                    (lv.Type is IManagedPointerType && Settings.AddressesEnabled()))
                {
                    continue;
                }

                var       varBoogieType    = Helpers.GetBoogieType(lv.Type);
                IVariable initialValue     = boogieTypeToLocalVariable[varBoogieType];
                var       storeInstruction = new LoadInstruction(0, lv, initialValue);
                storeInstruction.Label = String.Empty;
                instructions.Add(storeInstruction);
            }


            if (methodBody.MethodDefinition.IsConstructor)
            {
                IEnumerable <IFieldDefinition> fields = null;
                if (methodBody.MethodDefinition.ContainingTypeDefinition.IsGeneric)
                {
                    /*
                     *  This solves the issue of having a generic class (ie. class A<T>) and mismatches between field names.
                     *  If we just use ContaingTypeDefinition.Fields we have have a different IFieldDefinition than the ones found in the method bodies
                     *  Here, I want to be sure that we use A<T>.field as a field definition and not A.field
                     *  However, this could not be the ultimate solution and there could be a better way to tackle it.
                     */
                    var instanceOrSpecialized = TypeHelper.GetInstanceOrSpecializedNestedType(methodBody.MethodDefinition.ContainingTypeDefinition);
                    fields = instanceOrSpecialized.Fields;
                }
                else
                {
                    fields = methodBody.MethodDefinition.ContainingTypeDefinition.Fields;
                }

                var thisVariable = methodBody.Parameters[0];

                foreach (IFieldDefinition field in fields.Where(f => !f.IsStatic))
                {
                    var       fieldBoogieType  = Helpers.GetBoogieType(field.Type);
                    IVariable initialValue     = boogieTypeToLocalVariable[fieldBoogieType];
                    var       instanceAccess   = new InstanceFieldAccess(thisVariable, field);
                    var       storeInstruction = new StoreInstruction(0, instanceAccess, initialValue);
                    storeInstruction.Label = String.Empty;
                    instructions.Add(storeInstruction);
                }
            }

            methodBody.Variables.UnionWith(variables);
            int idx = 0;

            foreach (var i in instructions)
            {
                methodBody.Instructions.Insert(idx, i);
                idx++;
            }
        }
示例#17
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
        public override Addressable AddressOf(InstanceFieldAccess instanceFieldAccess)
        {
            var expr = Expression.LoadInstanceFieldAddr(instanceFieldAccess.Field, dispatcher.ReadAddr(instanceFieldAccess.Instance));

            return(new AddressExpression(instanceFieldAccess.Field.Type, expr));
        }
示例#18
0
        public static ISet <PTGNode> GetTargets(this PointsToGraph ptg, InstanceFieldAccess access)
        {
            var result = ptg.GetTargets(access.Instance, access.Field);

            return(result);
        }
示例#19
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
 //public abstract Addressable AddressOf(IReferenceable value);
 //public abstract Addressable AddressOf(IValue value);
 public abstract Addressable AddressOf(InstanceFieldAccess instanceFieldAccess);
示例#20
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
 public override Addressable AddressOf(InstanceFieldAccess instanceFieldAccess)
 {
     return(new InstanceField(instanceFieldAccess));
 }
示例#21
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
 public abstract Expression ReadInstanceField(InstanceFieldAccess instanceFieldAccess);
示例#22
0
        // some field initialization can be missing in constructors
        // example:

        /*
         * class Foo{
         *      int x; // this initialization is not added by the compiler
         *      int y = y;
         *  }
         */

        // therefore we are adding the initialization for each field at the top of every constructor.

        public void Transform()
        {
            // these variables hold the default value
            IDictionary <Helpers.BoogieType, LocalVariable> boogieTypeToLocalVariable =
                new Dictionary <Helpers.BoogieType, LocalVariable>();

            // they are the same stored in boogieTypeToLocalVariable
            IList <LocalVariable> variables
                = new List <LocalVariable>();

            // assignment of constants
            IList <Instruction> instructions
                = new List <Instruction>();

            CreateLocalVariablesWithDefaultValues(boogieTypeToLocalVariable, variables, instructions);

            // we need to initialize local variables.

            foreach (var lv in methodBody.Variables)
            {
                if (lv.IsParameter ||
                    // in the delegate handling this type of variables are not used
                    // calling get boogie type will crash
                    lv.Type is Microsoft.Cci.Immutable.FunctionPointerType)
                {
                    continue;
                }

                var       varBoogieType    = Helpers.GetBoogieType(lv);
                IVariable initialValue     = boogieTypeToLocalVariable[varBoogieType];
                var       storeInstruction = new LoadInstruction(0, lv, initialValue);
                storeInstruction.Label = String.Empty;
                instructions.Add(storeInstruction);
            }


            var fields = methodBody.MethodDefinition.ContainingTypeDefinition.Fields;

            if (methodBody.MethodDefinition.IsStaticConstructor)
            {
                foreach (IFieldDefinition field in fields.Where(f => f.IsStatic))
                {
                    var       fieldBoogieType  = Helpers.GetBoogieType(field);
                    IVariable initialValue     = boogieTypeToLocalVariable[fieldBoogieType];
                    var       staticAccess     = new StaticFieldAccess(field);
                    var       storeInstruction = new StoreInstruction(0, staticAccess, initialValue);
                    storeInstruction.Label = String.Empty;
                    instructions.Add(storeInstruction);
                }
            }
            else if (methodBody.MethodDefinition.IsConstructor)
            {
                var thisVariable = methodBody.Parameters[0];

                foreach (IFieldDefinition field in fields.Where(f => !f.IsStatic))
                {
                    var       fieldBoogieType  = Helpers.GetBoogieType(field);
                    IVariable initialValue     = boogieTypeToLocalVariable[fieldBoogieType];
                    var       instanceAccess   = new InstanceFieldAccess(thisVariable, field);
                    var       storeInstruction = new StoreInstruction(0, instanceAccess, initialValue);
                    storeInstruction.Label = String.Empty;
                    instructions.Add(storeInstruction);
                }
            }

            methodBody.Variables.UnionWith(variables);
            int idx = 0;

            foreach (var i in instructions)
            {
                methodBody.Instructions.Insert(idx, i);
                idx++;
            }
        }
示例#23
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
 public abstract StatementList WriteInstanceField(InstanceFieldAccess instanceFieldAccess, Expression value, InstructionTranslator instTranslator);
示例#24
0
文件: Memory.cs 项目: m7nu3l/TinyBCT
 public StatementList WriteInstanceField(InstanceFieldAccess instanceFieldAccess, IVariable value, InstructionTranslator instTranslator)
 {
     return(WriteInstanceField(instanceFieldAccess, ReadAddr(value), instTranslator));
 }
示例#25
0
        public void VisitMethod(MethodBody mBody, ControlFlowGraph cfg)
        {
            VisitLocals(mBody);

            // Going through the instructions via cfg nodes instead of directly iterating over the instructions
            // of the methodBody becuase Phi instructions may not have been inserted in the insts of the methodBody.
            foreach (var node in cfg.Nodes)
            {
                foreach (var instruction in node.Instructions)
                {
                    // System.Console.WriteLine("{0}", instruction.ToString());
                    // System.Console.WriteLine("{0}", instruction.GetType().FullName());
                    // System.Console.WriteLine();

                    if (instruction is LoadInstruction)
                    {
                        LoadInstruction lInst      = instruction as LoadInstruction;
                        IValue          rhsOperand = lInst.Operand;
                        if (rhsOperand is StaticFieldAccess)
                        {
                            StaticFieldAccess rhsAcc  = rhsOperand as StaticFieldAccess;
                            IFieldReference   fld     = rhsAcc.Field;
                            ITypeDefinition   fldType = fld.ContainingType.ResolvedType;
                            Stubber.CheckAndAdd(fldType);
                        }
                        // Note: calls to static methods and instance methods appear as a StaticMethodReference
                        else if (rhsOperand is StaticMethodReference)
                        {
                            StaticMethodReference sMethAddr    = rhsOperand as StaticMethodReference;
                            IMethodDefinition     tgtMeth      = sMethAddr.Method.ResolvedMethod;
                            ITypeDefinition       containingTy = tgtMeth.ContainingTypeDefinition;
                            Stubber.CheckAndAdd(containingTy);
                            IMethodDefinition addedMeth = Stubber.CheckAndAdd(tgtMeth);
                            // addrTakenMethods do not contain templates.
                            if (addedMeth != null)
                            {
                                addrTakenMethods.Add(addedMeth);
                            }
                        }
                        //Note: calls to virtual, abstract or interface methods appear as VirtualMethodReference
                        else if (rhsOperand is VirtualMethodReference)
                        {
                            VirtualMethodReference sMethAddr    = rhsOperand as VirtualMethodReference;
                            IMethodDefinition      tgtMeth      = sMethAddr.Method.ResolvedMethod;
                            ITypeDefinition        containingTy = tgtMeth.ContainingTypeDefinition;
                            ITypeDefinition        addedTy      = Stubber.CheckAndAdd(containingTy);
                            IMethodDefinition      addedMeth    = Stubber.CheckAndAdd(tgtMeth);
                            if (addedTy != null && addedMeth != null)
                            {
                                // addrTakenMethods do not contain templates.
                                addrTakenMethods.Add(addedMeth);
                                ProcessVirtualInvoke(addedMeth, addedTy, true);
                            }
                        }
                        else if (rhsOperand is Reference)
                        {
                            Reference      rhsRef = rhsOperand as Reference;
                            IReferenceable refOf  = rhsRef.Value;
                            if (refOf is StaticFieldAccess)
                            {
                                StaticFieldAccess refAcc  = refOf as StaticFieldAccess;
                                IFieldDefinition  fld     = refAcc.Field.ResolvedField;
                                ITypeDefinition   fldType = fld.ContainingType.ResolvedType;
                                Stubber.CheckAndAdd(fldType);
                                addrTakenStatFlds.Add(fld);
                            }
                            else if (refOf is IVariable)
                            {
                                IVariable refVar = refOf as IVariable;
                                if (!refVar.Type.IsValueType || refVar.Type.ResolvedType.IsStruct)
                                {
                                    addrTakenLocals.Add(refVar);
                                }
                            }
                            else if (refOf is InstanceFieldAccess)
                            {
                                InstanceFieldAccess refAcc = refOf as InstanceFieldAccess;
                                IFieldDefinition    fld    = refAcc.Field.ResolvedField;
                                addrTakenInstFlds.Add(fld);
                            }
                            else if (refOf is ArrayElementAccess)
                            {
                                // All arrays will be added into domX as potential address taken.
                            }
                        }
                    }
                    else if (instruction is StoreInstruction)
                    {
                        StoreInstruction sInst = instruction as StoreInstruction;
                        IAssignableValue lhs   = sInst.Result;
                        if (lhs is StaticFieldAccess)
                        {
                            StaticFieldAccess lhsAcc  = lhs as StaticFieldAccess;
                            IFieldReference   fld     = lhsAcc.Field;
                            ITypeDefinition   fldType = fld.ContainingType.ResolvedType;
                            Stubber.CheckAndAdd(fldType);
                        }
                    }
                    else if (instruction is CreateObjectInstruction)
                    {
                        CreateObjectInstruction newObjInst = instruction as CreateObjectInstruction;
                        ITypeReference          objType    = newObjInst.AllocationType;
                        ITypeDefinition         objTypeDef = objType.ResolvedType;
                        if (objTypeDef is IGenericTypeInstance)
                        {
                            objTypeDef = objTypeDef.ResolvedType;
                        }
                        ITypeDefinition addedTy = Stubber.CheckAndAdd(objTypeDef);
                        if (addedTy != null && !allocClasses.Contains(addedTy))
                        {
                            allocClasses.Add(addedTy);
                        }
                    }
                    else if (instruction is CreateArrayInstruction)
                    {
                        CreateArrayInstruction newArrInst  = instruction as CreateArrayInstruction;
                        ITypeReference         elemType    = newArrInst.ElementType;
                        ITypeDefinition        elemTypeDef = elemType.ResolvedType;
                        ITypeDefinition        addedTy     = Stubber.CheckAndAdd(elemTypeDef);
                        if (addedTy != null && !allocClasses.Contains(addedTy))
                        {
                            allocClasses.Add(addedTy);
                        }
                    }
                    else if (instruction is MethodCallInstruction)
                    {
                        MethodCallInstruction invkInst       = instruction as MethodCallInstruction;
                        IMethodReference      callTgt        = invkInst.Method;
                        ITypeReference        containingType = callTgt.ContainingType;
                        ITypeDefinition       declType       = containingType.ResolvedType;
                        IMethodDefinition     callTgtDef     = callTgt.ResolvedMethod;
                        ITypeDefinition       addedType      = Stubber.CheckAndAdd(declType);
                        IMethodDefinition     addedMeth      = Stubber.CheckAndAdd(callTgtDef);
                        MethodCallOperation   callType       = invkInst.Operation;
                        if (callType == MethodCallOperation.Virtual && addedType != null && addedMeth != null)
                        {
                            ProcessVirtualInvoke(addedMeth, addedType, false);
                        }
                    }
                    else
                    {
                        // System.Console.WriteLine("{0}", instruction.ToString());
                        // System.Console.WriteLine("Not currently handled: {0}", instruction.GetType().ToString());
                        // System.Console.WriteLine();
                    }
                }
            }
        }