Пример #1
0
 /// <summary>
 /// Creates a fresh local var of the given Type and adds it to the
 /// Bpl Implementation
 /// </summary>
 /// <param name="typeReference"> The type of the new variable </param>
 /// <returns> A fresh Variable with automatic generated name and location </returns>
 public Bpl.Variable CreateFreshLocal(ITypeReference typeReference) {
   Bpl.IToken loc = Bpl.Token.NoToken; // Helper Variables do not have a location
   Bpl.Type t = TranslationHelper.CciTypeToBoogie(typeReference);
   Bpl.LocalVariable v = new Bpl.LocalVariable(loc, new Bpl.TypedIdent(loc, TranslationHelper.GenerateTempVarName(), t));
   ILocalDefinition dummy = new LocalDefinition(); // Creates a dummy entry for the Dict, since only locals in the dict are translated to boogie
   localVarMap.Add(dummy, v);
   return v;
 }
        private INamedTypeDefinition GenerateTypeA(IUnitNamespace rootNamespace)
        {
            var nt = Host.NameTable;
            var typeA = new NamespaceTypeDefinition
                            {
                                ContainingUnitNamespace = rootNamespace,
                                Name = nt.GetNameFor("A"),
                                InternFactory = Host.InternFactory,
                                IsClass = true
                            };
            var typeParameter = new GenericTypeParameter
                                    {
                                        Name = nt.GetNameFor("T"),
                                        InternFactory = Host.InternFactory,
                                        DefiningType = typeA,
                                    };
            typeA.GenericParameters.Add(typeParameter);

            var baseGetMethod = new MethodDefinition
                                    {
                                        Name = nt.GetNameFor("Get"),
                                        IsCil = true,
                                        IsVirtual = true,
                                        Visibility = TypeMemberVisibility.Assembly,
                                        Type = typeParameter,
                                        ContainingTypeDefinition = typeA,
                                        InternFactory = Host.InternFactory,
                                        IsNewSlot = true
                                    };
            typeA.Methods.Add(baseGetMethod);

            var il = new ILGenerator(Host);
            var localVar = new LocalDefinition
            {
                Type = typeParameter,
                Name = nt.GetNameFor("local1"),
            };

            // tricky moment, ILGeneratorMethodBody fills internal collection of local vars only in constructor.
            // lines below should not be swapped

            il.AddVariableToCurrentScope(localVar);
            var body = new ILGeneratorMethodBody(il, true, 1) {MethodDefinition = baseGetMethod};
            baseGetMethod.Body = body;

            il.Emit(OperationCode.Ldloca, localVar);
            il.Emit(OperationCode.Initobj, typeParameter);
            il.Emit(OperationCode.Ldloc_0);
            il.Emit(OperationCode.Ret);

            return typeA;
        }
Пример #3
0
        protected override void VisitDeclarationSyntax(DeclarationSyntax pNode)
        {
            Visit(pNode.Value);

            var isTuple = pNode.Value.Type.IsTuple;

            for (int i = 0; i < pNode.Variables.Count; i++)
            {
                if (!SyntaxHelper.IsDiscard(pNode.Variables[i]))
                {
                    if (_locals.IsVariableDefinedInScope(pNode.Variables[i].Value))
                    {
                        CompilerErrors.IdentifierAlreadyDeclared(pNode.Variables[i], pNode.Span);
                    }
                    else
                    {
                        //We do not allow variables to have the same names as types
                        //This makes it easier to check for "static" method/fields
                        if (SmallTypeCache.IsTypeDefined(pNode.Variables[i].Value))
                        {
                            CompilerErrors.ValueDefinedAsType(pNode.Variables[i], pNode.Variables[i].Span);
                        }
                        else
                        {
                            //For tuple types we set the individual variables to the tuple field type... not the tuple itself
                            var t = isTuple ? pNode.Value.Type.GetFieldType(i) : pNode.Value.Type;

                            //Report expression errors and change the type to Undefined so we don't get further no expression errors
                            if (pNode.Value.Type == SmallTypeCache.NoValue)
                            {
                                CompilerErrors.ExpressionNoValue(pNode.Value.Span);
                                t = SmallTypeCache.Undefined;
                            }

                            pNode.Variables[i].SetType(t);
                            _locals.DefineVariableInScope(pNode.Variables[i].Value, LocalDefinition.Create(pNode.IsConst, pNode.Variables[i].Type));
                        }
                    }
                }
            }

            //Check that we are declaring the proper number of variables
            if (isTuple && pNode.Value.Type.GetFieldCount() != pNode.Variables.Count)
            {
                CompilerErrors.DeclarationCountMismatch(pNode.Value.Type.GetFieldCount(), pNode.Variables.Count, pNode.Span);
            }
        }
            protected override void RewriteStoreField(IOperation op)
            {
                var fieldReference = op.Value as IFieldReference;

                Contract.Assert(fieldReference != null);

                if (fieldReference.ContainingType.IsEnum == false)
                {
                    var storeFieldCounter = new FieldReference()
                    {
                        Name           = base.host.NameTable.GetNameFor(MemberHelper.GetMemberSignature(fieldReference, NameFormattingOptions.None) + "$$storeCount"),
                        Type           = base.host.PlatformType.SystemInt64,
                        InternFactory  = base.host.InternFactory,
                        ContainingType = fieldReference.ContainingType,
                        IsStatic       = false
                    };

                    // save the variable that is on the top of stack
                    var name = "XXX_" + fieldReference.Name.ToString();
                    var def  = new LocalDefinition {
                        Name = base.host.NameTable.GetNameFor(name),
                        Type = fieldReference.Type
                    };
                    if (base.methodBody.LocalVariables == null)
                    {
                        base.methodBody.LocalVariables = new List <ILocalDefinition>(1);
                    }
                    base.methodBody.LocalVariables.Add(def);

                    // store top-of-stack into a local.  This is the value the stfld uses
                    generator.Emit(OperationCode.Stloc, def);

                    base.generator.Emit(OperationCode.Dup);                      // load "this" onto stack
                    base.generator.Emit(OperationCode.Dup);                      // load "this" onto stack
                    base.generator.Emit(OperationCode.Ldfld, storeFieldCounter); // load field$$storeCount onto stack
                    base.generator.Emit(OperationCode.Ldc_I4_1);                 // load 1 onto stack
                    base.generator.Emit(OperationCode.Conv_I8);                  // convert to int64
                    base.generator.Emit(OperationCode.Add);                      // add field$storeCount + 1
                    base.generator.Emit(OperationCode.Stfld, storeFieldCounter); // store result of add to field$$storeCount

                    // restore the var we saved from the local
                    generator.Emit(OperationCode.Ldloc, def);
                }

                // now do the original stfld
                base.RewriteStoreField(op);
            }
        void EmitDisposeAndClean(CodeGenerator cg)
        {
            // enumerator.Dispose()
            if (_disposeMethod != null)
            {
                // TODO: if (enumerator != null)

                if (_enumeratorLoc.Type.IsValueType)
                {
                    _enumeratorLoc.EmitLoadAddress(cg.Builder);
                }
                else
                {
                    _enumeratorLoc.EmitLoad(cg.Builder);
                }

                cg.EmitCall(ILOpCode.Callvirt, _disposeMethod)
                .Expect(SpecialType.System_Void);
            }

            //// enumerator = null;
            //if (!_enumeratorLoc.Type.IsValueType)
            //{
            //    cg.Builder.EmitNullConstant();
            //    cg.Builder.EmitLocalStore(_enumeratorLoc);
            //}

            //
            if (_aliasedValueLoc != null)
            {
                cg.ReturnTemporaryLocal(_aliasedValueLoc);
                _aliasedValueLoc = null;
            }

            cg.ReturnTemporaryLocal(_enumeratorLoc);
            _enumeratorLoc = null;

            // unbind
            _moveNextMethod = null;
            _disposeMethod  = null;
            _currentValue   = null;
            _currentKey     = null;
            _current        = null;
            _iterator_next  = null;
        }
Пример #6
0
        protected override LocalDefinition DeclareLocalInternal(
            Microsoft.Cci.ITypeReference type,
            object identity,
            string name,
            bool isCompilerGenerated,
            LocalSlotConstraints constraints,
            bool isDynamic,
            ImmutableArray <TypedConstant> dynamicTransformFlags)
        {
            LocalDefinition local;

            if (identity != null)
            {
                int slot = this.getPreviousLocalSlot(identity, type, constraints);
                if (slot >= 0)
                {
                    Debug.Assert(this.allLocals[slot].Identity == null);

                    local = new LocalDefinition(
                        identity: identity,
                        name: name,
                        type: type,
                        slot: slot,
                        isCompilerGenerated: isCompilerGenerated,
                        constraints: constraints,
                        isDynamic: isDynamic,
                        dynamicTransformFlags: dynamicTransformFlags);
                    this.allLocals[slot] = local;
                    return(local);
                }
            }

            local = new LocalDefinition(
                identity: identity,
                name: name,
                type: type,
                slot: this.allLocals.Count,
                isCompilerGenerated: isCompilerGenerated,
                constraints: constraints,
                isDynamic: isDynamic,
                dynamicTransformFlags: dynamicTransformFlags);
            this.allLocals.Add(local);
            return(local);
        }
Пример #7
0
        protected override void VisitMemberAccessSyntax(MemberAccessSyntax pNode)
        {
            Visit(pNode.Identifier);

            //Save current local definitions
            //Mark the current type we are on so error messages can be more descriptive
            var l = _locals;

            using (var t = Store.AddValue("__Type", pNode.Identifier.Type))
            {
                //If field doesn't exist or something went wrong, stop checking things to reduce redundant errors
                if (CurrentType != SmallTypeCache.Undefined)
                {
                    //For methods and arrays we need to allow existing variables, but member access should only allow the struct's fields
                    if (NeedToCopyLocals(pNode.Value))
                    {
                        _locals = _locals.Copy();
                    }
                    else
                    {
                        _locals = new ScopeCache <LocalDefinition>();
                    }

                    //Namespaces return a null type
                    if (CurrentType != null)
                    {
                        _locals.AddScope();
                        foreach (var f in CurrentType.GetFields())
                        {
                            if (!_locals.IsVariableDefinedInScope(f.Name))
                            {
                                _locals.DefineVariableInScope(f.Name, LocalDefinition.Create(false, f.Type));
                            }
                        }
                    }

                    Visit(pNode.Value);
                }
            }

            //Restore local definitions
            Namespace = null;
            _locals   = l;
        }
Пример #8
0
            public void Dispose()
            {
                if (_loc != null)
                {
                    _cg.ReturnTemporaryLocal(_loc);

                    _loc = null;
                }
                else if (_tempName != null)
                {
                    // <temporary>.RemoveKey(name)
                    Debug.Assert(_cg.TemporalLocalsPlace != null);
                    _cg.TemporalLocalsPlace.EmitLoad(_cg.Builder);
                    _cg.EmitIntStringKey(_tempName);
                    _cg.EmitPop(_cg.EmitCall(System.Reflection.Metadata.ILOpCode.Callvirt, _cg.CoreMethods.PhpArray.RemoveKey_IntStringKey));

                    _tempName = null;
                }
            }
        private static void EmitUnicodeStringMarshalling(List <ILocalDefinition> locals, ILGenerator ilGenerator, IMethodReference getOffsetToStringData, ITypeReference stringType)
        {
            var pinnedLocal = new LocalDefinition {
                IsPinned = true, Type = stringType
            };

            locals.Add(pinnedLocal);

            var nullCaseLabel = new ILGeneratorLabel();

            ilGenerator.Emit(OperationCode.Stloc, pinnedLocal);
            ilGenerator.Emit(OperationCode.Ldloc, pinnedLocal);
            ilGenerator.Emit(OperationCode.Conv_I);
            ilGenerator.Emit(OperationCode.Dup);
            ilGenerator.Emit(OperationCode.Brfalse_S, nullCaseLabel);
            ilGenerator.Emit(OperationCode.Call, getOffsetToStringData);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.MarkLabel(nullCaseLabel);
        }
        public LoadInterfaceMethodDataAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            if (context.GetConstantInReg("rcx") is {} castConstant &&
                castConstant.Value is NewSafeCastResult castResult &&
                context.GetConstantInReg("rdx") is {} interfaceConstant &&
                interfaceConstant.Value is TypeDefinition interfaceType &&
                context.GetConstantInReg("r8") is {} slotConstant &&
                slotConstant.Value is int slot &&
                context.Actions.FirstOrDefault(a => a is LocateSpecificInterfaceOffsetAction) is LocateSpecificInterfaceOffsetAction locator
                )
            {
                _invokedOn     = castResult.original;
                _interfaceType = interfaceType;
                _slotNumber    = slot;
                resolvedMethod = SharedState.VirtualMethodsBySlot[(ushort)(locator._matchingInterfaceOffset.offset + _slotNumber)];

                _resultConstant = context.MakeConstant(typeof(MethodDefinition), resolvedMethod, reg: "rax");
            }
        }
        private void PostprocessNonBlittableArrayArguments(IMethodDefinition methodDefinition, List <ILocalDefinition> locals, Dictionary <IParameterDefinition, ILocalDefinition> paramToLocalMap, ILGenerator ilGenerator)
        {
            bool hasReturnValue = methodDefinition.Type != this.host.PlatformType.SystemVoid;

            if (IsAnyParameterNonBlittableArray(methodDefinition))
            {
                var retLocal = new LocalDefinition
                {
                    IsPinned = false,
                    Type     = methodDefinition.Type
                };

                if (hasReturnValue)
                {
                    locals.Add(retLocal);
                    ilGenerator.Emit(OperationCode.Stloc, retLocal);
                }

                var exitLabel = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Leave, exitLabel);
                ilGenerator.BeginFinallyBlock();

                foreach (var elem in methodDefinition.Parameters)
                {
                    ILocalDefinition t;
                    if (paramToLocalMap.TryGetValue(elem, out t))
                    {
                        ilGenerator.Emit(OperationCode.Ldloc, t);
                        ilGenerator.Emit(OperationCode.Call, this.stringArrayMarshallingEpilog); // TODO: Generalize for other array types
                    }
                }

                ilGenerator.Emit(OperationCode.Endfinally);
                ilGenerator.EndTryBody();
                ilGenerator.MarkLabel(exitLabel);

                if (hasReturnValue)
                {
                    ilGenerator.Emit(OperationCode.Ldloc, retLocal);
                }
            }
        }
        private void PreprocessNonBlittableArrayArguments(List <ILocalDefinition> locals, Dictionary <IParameterDefinition, ILocalDefinition> paramToLocalMap, ILGenerator ilGenerator, int argumentCount, Func <int, IParameterDefinition> parameterProvider)
        {
            bool beginTryBody = false;

            for (int i = 0; i < argumentCount; ++i)
            {
                var parameter = parameterProvider(i);
                var arrayType = parameter.Type.ResolvedType as IArrayType;
                if (arrayType != null)
                {
                    if (TypeHelper.TypesAreEquivalent(arrayType.ElementType, this.host.PlatformType.SystemString))
                    {
                        var intPtrArrayType = new VectorTypeReference {
                            ElementType = this.host.PlatformType.SystemIntPtr, Rank = 1
                        }.ResolvedArrayType;

                        Ldarg(ilGenerator, parameter, i);
                        ilGenerator.Emit(OperationCode.Ldlen);
                        ilGenerator.Emit(OperationCode.Conv_I4); // I guess this breaks in large gc array mode
                        ilGenerator.Emit(OperationCode.Newarr, intPtrArrayType);

                        // IntPtr[]
                        var intPtrArray = new LocalDefinition
                        {
                            IsPinned = false,
                            Type     = intPtrArrayType
                        };

                        locals.Add(intPtrArray);
                        paramToLocalMap.Add(parameter, intPtrArray);

                        ilGenerator.Emit(OperationCode.Stloc, intPtrArray);
                        beginTryBody = true;
                    }
                }
            }

            if (beginTryBody)
            {
                ilGenerator.BeginTryBody();
            }
        }
Пример #13
0
            public override ILocalDefinition Rewrite(ILocalDefinition localDefinition)
            {
                if (localDefinition.MethodDefinition != this.moveNext) // might happen to visit an already replaced local
                {
                    return(localDefinition);
                }
                ILocalDefinition loc;

                if (!this.localTable.TryGetValue(localDefinition, out loc))
                {
                    loc = new LocalDefinition()
                    {
                        MethodDefinition = this.iterator,
                        Name             = localDefinition.Name,
                        Type             = localDefinition.Type,
                    };
                    this.localTable.Add(localDefinition, loc);
                }
                return(loc);
            }
Пример #14
0
        private void AddExpressionTemp(LocalDefinition temp)
        {
            // in some cases like stack locals, there is no slot allocated.
            if (temp == null)
            {
                return;
            }

            ArrayBuilder <LocalDefinition> exprTemps = _expressionTemps;

            if (exprTemps == null)
            {
                exprTemps = ArrayBuilder <LocalDefinition> .GetInstance();

                _expressionTemps = exprTemps;
            }

            Debug.Assert(!exprTemps.Contains(temp));
            exprTemps.Add(temp);
        }
Пример #15
0
        private ILocalDefinition GetOrCreateLocal(int depth, ITypeReference type)
        {
            Contract.Requires(0 <= depth);
            Contract.Requires(type != null);

            ILocalDefinition local;
            var key = KeyForLocal(depth, type);

            if (this.createdLocals.TryGetValue(key, out local))
            {
                return(local);
            }
            local = new LocalDefinition()
            {
                Name             = this.host.NameTable.GetNameFor(NameForLocal(depth, type)),
                MethodDefinition = this.methodDefinition,
                Type             = type,
            };
            this.createdLocals.Add(key, local);
            return(local);
        }
Пример #16
0
        public GraphRandomStateGenerator(IModule module, PeReader.DefaultHost host, Log.Log logger, CfgManipulator cfgManipulator, Helper helperClass, Graph.Graph graph, MethodCfg methodCfg, bool debugging) {

            this.module = module;
            this.host = host;
            this.logger = logger;
            this.cfgManipulator = cfgManipulator;            
            this.helperClass = helperClass;
            this.graph = graph;
            this.methodCfg = methodCfg;
            this.debugging = debugging;

            // add local random generator variable
            this.tempRandomLocal = new LocalDefinition();
            this.tempRandomLocal.IsReference = false;
            this.tempRandomLocal.IsPinned = false;
            this.tempRandomLocal.IsModified = false;
            this.tempRandomLocal.Type = this.helperClass.systemRandom;
            this.tempRandomLocal.MethodDefinition = methodCfg.method;
            cfgManipulator.addLocalVariable(this.tempRandomLocal);


        }
Пример #17
0
        public CallVirtualMethodAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var inReg = context.GetOperandInRegister(Utils.GetRegisterNameNew(instruction.MemoryBase));

            if (!(inReg is ConstantDefinition cons) || !(cons.Value is Il2CppClassIdentifier klass))
            {
                return;
            }

            var classReadFrom = klass.backingType;

            var readOffset = instruction.MemoryDisplacement;

            Called = Utils.GetMethodFromReadKlassOffset((int)readOffset);

            if (Called == null)
            {
                return;
            }

            CalledOn = context.GetLocalInReg("rcx");
        }
Пример #18
0
        private static EncLocalInfo GetLocalInfo(
            IReadOnlyDictionary <SyntaxNode, int> declaratorToIndex,
            LocalDefinition localDef)
        {
            // Local symbol will be null for short-lived temporaries.
            var local = (LocalSymbol)localDef.Identity;

            if ((object)local != null)
            {
                var syntaxRefs = local.DeclaringSyntaxReferences;
                Debug.Assert(!syntaxRefs.IsDefault);

                if (!syntaxRefs.IsDefaultOrEmpty)
                {
                    var syntax = syntaxRefs[0].GetSyntax();
                    var offset = declaratorToIndex[syntax];
                    return(new EncLocalInfo(offset, localDef.Type, localDef.Constraints, (int)local.TempKind));
                }
            }

            return(new EncLocalInfo(localDef.Type, localDef.Constraints));
        }
Пример #19
0
        void EmitDisposeAndClean(CodeGenerator cg)
        {
            // enumerator.Dispose()
            if (_disposeMethod != null)
            {
                // TODO: if (enumerator != null)

                if (_enumeratorLoc.Type.IsValueType)
                {
                    cg.Builder.EmitLocalAddress(_enumeratorLoc);
                }
                else
                {
                    cg.Builder.EmitLocalLoad(_enumeratorLoc);
                }

                cg.EmitCall(CallOpCode(_disposeMethod, (TypeSymbol)_enumeratorLoc.Type), _disposeMethod)
                .Expect(SpecialType.System_Void);
            }

            //// enumerator = null;
            //if (!_enumeratorLoc.Type.IsValueType)
            //{
            //    cg.Builder.EmitNullConstant();
            //    cg.Builder.EmitLocalStore(_enumeratorLoc);
            //}

            //
            cg.ReturnTemporaryLocal(_enumeratorLoc);
            _enumeratorLoc = null;

            // unbind
            _moveNextMethod = null;
            _disposeMethod  = null;
            _currentValue   = null;
            _currentKey     = null;
            _current        = null;
        }
Пример #20
0
        static void AddAllRecipes()
        {
            string[]           itemHashes = File.ReadAllLines("ItemHashes.txt");  // Item hash text file dump, one item hash per line
            FunctionDefinition function   = CreateFunction(@"_\kyle873\AddAllRecipes.script", "AddAllRecipes");
            Label endLabel             = cg.DefineLabel();
            ParameterDefinition gi     = CreateParam(function, "gameInstance", function, gameInstance);
            LocalDefinition     type   = CreateLocal(function, "type", function, stringNative);
            LocalDefinition     amount = CreateLocal(function, "amount", function, stringNative);

            OpAssign(amount, "1");

            foreach (string hash in itemHashes.Where(h => h.Contains("Recipe")))
            {
                OpAssign(type, hash);

                OpCall(endLabel, giveItem, gi, type, amount);
            }

            cg.MarkLabel(endLabel);
            cg.Emit(Opcode.Nop);

            function.Code.AddRange(cg.GetCode());
        }
Пример #21
0
        internal void EmitPrepare(CodeGenerator cg)
        {
            if (_currentValue != null && _aliasedValues && _currentValue.ReturnType == cg.CoreTypes.PhpAlias &&
                cg.GeneratorStateMachineMethod == null)
            {
                _aliasedValueLoc = cg.GetTemporaryLocal(_currentValue.ReturnType, immediateReturn: false);

                cg.Builder.EmitNullConstant();
                cg.Builder.EmitLocalStore(_aliasedValueLoc);
            }

            var nextedge = NextBlock.NextEdge as ForeachMoveNextEdge;

            if (_currentKey == null && nextedge.KeyVariable != null && !IsAPairValue(_current.ReturnType, out _, out _))
            {
                // KeyVariable will be iterated from 1
                _synthesizedIndexLoc = cg.GetTemporaryLocal(cg.CoreTypes.Long, true, immediateReturn: false);

                // Template: KeyVariable = 0;
                cg.Builder.EmitLongConstant(0L);
                _synthesizedIndexLoc.EmitStore();
            }
        }
        private static void EmitBlittableTypeArrayMarshalling(List <ILocalDefinition> locals, ILGenerator ilGenerator, IArrayType arrayType)
        {
            var nullCaseLabel = new ILGeneratorLabel();

            // [0] T& pinned x
            var pinnedLocal = new LocalDefinition
            {
                IsPinned    = true,
                IsReference = true,
                Type        = arrayType.ElementType
            };

            // [1] T[] V_1,
            var duplicatearray = new LocalDefinition
            {
                IsPinned = false,
                Type     = arrayType
            };

            locals.Add(pinnedLocal);
            locals.Add(duplicatearray);

            ilGenerator.Emit(OperationCode.Dup);
            ilGenerator.Emit(OperationCode.Stloc, duplicatearray);
            ilGenerator.Emit(OperationCode.Brfalse, nullCaseLabel);
            ilGenerator.Emit(OperationCode.Ldloc, duplicatearray);
            ilGenerator.Emit(OperationCode.Ldlen);
            ilGenerator.Emit(OperationCode.Conv_I4);
            ilGenerator.Emit(OperationCode.Brfalse, nullCaseLabel);
            ilGenerator.Emit(OperationCode.Ldloc, duplicatearray);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Ldelema, arrayType.ElementType);
            ilGenerator.Emit(OperationCode.Stloc, pinnedLocal);
            ilGenerator.MarkLabel(nullCaseLabel);
            ilGenerator.Emit(OperationCode.Ldloc, pinnedLocal);
            ilGenerator.Emit(OperationCode.Conv_I);
        }
Пример #23
0
        // this function generates code that sets the random state
        public List<IOperation> generateCodeSetRandomState(LocalDefinition intStateLocal) {

            List<IOperation> operations = new List<IOperation>();

            operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, this.tempRandomLocal));
            operations.Add(this.helperClass.createNewOperation(OperationCode.Ldc_I4, this.graph.graphValidPathCount));
            operations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.helperClass.systemRandomNext));
            operations.Add(this.helperClass.createNewOperation(OperationCode.Stloc, intStateLocal));


            // if debugging is activated => print used global state
            if (this.debugging) {

                operations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, "Current State: "));
                operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloca, intStateLocal));
                operations.Add(this.helperClass.createNewOperation(OperationCode.Call, this.helperClass.int32ToString));
                operations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, " (possible: 0 - " + (this.graph.graphValidPathCount - 1).ToString() + ")"));
                operations.Add(this.helperClass.createNewOperation(OperationCode.Call, this.helperClass.stringConcatThree));
                operations.Add(this.helperClass.createNewOperation(OperationCode.Call, this.helperClass.systemConsoleWriteLine));

            }

            return operations;
        }
Пример #24
0
        ILocalDefinition addDeadLocal(string targetType)
        {
            LocalDefinition result = new LocalDefinition();

            result.IsReference      = result.IsPinned = result.IsModified = false;
            result.MethodDefinition = methodCfg.method;

            // Switch for local type (TODO: Support more).
            // Maybe create multiple variables of the same type to add diffusion (but add upper bound).
            INamespaceTypeReference type = null;

            switch (targetType)
            {
            case "System.Int32":   type = host.PlatformType.SystemInt32; break;

            case "System.String":  type = host.PlatformType.SystemString; break;

            case "System.Boolean": type = host.PlatformType.SystemBoolean; break;

            default:
                throw new ArgumentException("Cannot add dead local of unsupported type.");
            }

            // Add the new local variable to our method.
            result.Type = type;
            manipulator.addLocalVariable(result);

            // Initialize dead local variable in the method's first basic block according to its type.
            // TODO: This might be used to easily detect dead locals. Improve on this.
            var loadSequence = loadBogusParameter(type);

            loadSequence.Add(createNewOperation(OperationCode.Stloc, result));

            methodCfg.startBasicBlock.operations.InsertRange(0, loadSequence);
            return(result);
        }
Пример #25
0
 /// <summary>
 /// Returns a <see cref="LocalDefinition"/> previously obtained from <see cref="GetTemporaryLocal"/> to the
 /// pool of locals available for reuse.
 /// </summary>
 /// <param name="definition">The <see cref="LocalDefinition"/> to return to the pool.</param>
 public void ReturnTemporaryLocal(LocalDefinition /*!*/ definition)
 {
     _il.LocalSlotManager.FreeSlot(definition);
 }
Пример #26
0
    private ILocalDefinition ExtractExceptionContainer(DecompiledBlock nestedBlock, ITypeReference exceptionType) {
      Contract.Requires(nestedBlock != null);
      Contract.Requires(exceptionType != null);
      Contract.Ensures(Contract.Result<ILocalDefinition>() != null);

      Contract.Assume(nestedBlock.Statements.Count > 0);
      int i = 0;
      while (nestedBlock.Statements[i] is LocalDeclarationStatement) { i++; Contract.Assume(i < nestedBlock.Statements.Count); };
      var firstStatement = nestedBlock.Statements[i++];
      var firstBlock = firstStatement as DecompiledBlock;
      while (firstBlock != null) {
        Contract.Assume(firstBlock.Statements.Count > 0);
        i = 0;
        while (firstBlock.Statements[i] is LocalDeclarationStatement) { i++; Contract.Assume(i < firstBlock.Statements.Count); };
        firstStatement = firstBlock.Statements[i++];
        nestedBlock = firstBlock;
        firstBlock = firstStatement as DecompiledBlock;
      }
      //Ignoring any local declarations inserted for lexical scopes, any decompiled block that does not start with a nested block, starts with a label.
      Contract.Assume(firstStatement is LabeledStatement);
      if (nestedBlock.Statements.Count > i) {
        var exprStatement = nestedBlock.Statements[i] as ExpressionStatement;
        if (exprStatement != null) {
          nestedBlock.Statements.RemoveRange(i-1, 2);
          if (exprStatement.Expression is PopValue) return Dummy.LocalVariable;
          var assignment = exprStatement.Expression as Assignment;
          if (assignment != null && assignment.Source is PopValue) {
            var local = assignment.Target.Definition as ILocalDefinition;
            if (local != null) return local; //if not, this is not a recognized code pattern.
          }
        }
        // can't find the local, so just introduce one and leave its value on the stack
        var ld = new LocalDefinition() {
          Type = exceptionType,
        };
        var pushStatement = new PushStatement() {
          ValueToPush = new BoundExpression() {
            Definition = ld,
            Type = exceptionType,
          },
        };
        nestedBlock.Statements.Insert(0, pushStatement);
        return ld;
      } else {
        //Valid IL should always have at least one instruction to consume the exception value as well as a branch out of the handler block.
        Contract.Assume(false);
        return Dummy.LocalVariable;
      }
    }
Пример #27
0
        ILocalDefinition addDeadLocal(string targetType)
        {
            LocalDefinition result = new LocalDefinition();

            result.IsReference = result.IsPinned = result.IsModified = false;
            result.MethodDefinition = methodCfg.method;

            // Switch for local type (TODO: Support more).
            // Maybe create multiple variables of the same type to add diffusion (but add upper bound).
            INamespaceTypeReference type = null;

            switch(targetType) {
            case "System.Int32":   type = host.PlatformType.SystemInt32; break;
            case "System.String":  type = host.PlatformType.SystemString; break;
            case "System.Boolean": type = host.PlatformType.SystemBoolean; break;
            default:
                throw new ArgumentException("Cannot add dead local of unsupported type.");
            }

            // Add the new local variable to our method.
            result.Type = type;
            manipulator.addLocalVariable(result);

            // Initialize dead local variable in the method's first basic block according to its type.
            // TODO: This might be used to easily detect dead locals. Improve on this.
            var loadSequence = loadBogusParameter(type);
            loadSequence.Add(createNewOperation(OperationCode.Stloc, result));

            methodCfg.startBasicBlock.operations.InsertRange(0, loadSequence);
            return result;
        }
Пример #28
0
 public override ILocalDefinition Rewrite(ILocalDefinition localDefinition) {
   if (localDefinition.MethodDefinition/*.InternedKey*/ == this.sourceMethod/*.InternedKey*/) {
     ILocalDefinition alreadyReparentedLocal;
     if (!this.newLocals.TryGetValue(localDefinition, out alreadyReparentedLocal)) {
       var ld = new LocalDefinition() {
         MethodDefinition = this.targetMethod,
         Name = localDefinition.Name,
         Type = localDefinition.Type,
       };
       this.newLocals.Add(localDefinition, ld);
       alreadyReparentedLocal = ld;
     }
     return alreadyReparentedLocal;
   }
   return localDefinition;
 }
Пример #29
0
 /// <summary>
 /// Rewrites the children of the specified local definition.
 /// </summary>
 /// <param name="localDefinition"></param>
 public override void RewriteChildren(LocalDefinition localDefinition) {
   if (localDefinition.MethodDefinition.InternedKey == this.targetMethod.InternedKey)
     localDefinition.MethodDefinition = this.sourceMethod;
   base.RewriteChildren(localDefinition);
 }
Пример #30
0
      protected override void EmitOperation(IOperation operation) {
        if (operation.Offset <= this.lastOffset) {
          if (this.parent.IsCallToContractMethod(operation)) {
            EmitContractCall(operation);
          } else {
            base.EmitOperation(operation);
          }
          if (!this.moveNextMethod && operation.Offset == this.lastOffset) {
            #region All done: add return statement
            if (this.parent.currentMethod.Type.TypeCode != PrimitiveTypeCode.Void) {
              var ld = new LocalDefinition() {
                Type = this.parent.currentMethod.Type,
              };
              base.EmitOperation(new Operation() { OperationCode = OperationCode.Ldloc, Value = ld, });
              base.TrackLocal(ld);
            }
            base.EmitOperation(new Operation() { OperationCode = OperationCode.Ret, });
            #endregion All done: add return statement
          }
        }

      }
Пример #31
0
        public override IStatement Rewrite(IForEachStatement forEachStatement)
        {
            ILocalDefinition foreachLocal;
            var key = forEachStatement.Collection.Type.InternedKey;

            ITypeReference   enumeratorType;
            IMethodReference getEnumerator;
            IMethodReference getCurrent;

            var gtir = forEachStatement.Collection.Type as IGenericTypeInstanceReference;

            if (gtir != null)
            {
                var            typeArguments         = gtir.GenericArguments;
                ITypeReference genericEnumeratorType = new Immutable.GenericTypeInstanceReference(this.host.PlatformType.SystemCollectionsGenericIEnumerator, typeArguments, this.host.InternFactory);
                ITypeReference genericEnumerableType = new Immutable.GenericTypeInstanceReference(this.host.PlatformType.SystemCollectionsGenericIEnumerable, typeArguments, this.host.InternFactory);
                enumeratorType = genericEnumeratorType;
                getEnumerator  = new SpecializedMethodReference()
                {
                    CallingConvention = CallingConvention.HasThis,
                    ContainingType    = genericEnumerableType,
                    InternFactory     = this.host.InternFactory,
                    Name                 = this.host.NameTable.GetNameFor("GetEnumerator"),
                    Parameters           = new List <IParameterTypeInformation>(),
                    Type                 = genericEnumeratorType,
                    UnspecializedVersion = new MethodReference()
                    {
                        CallingConvention = CallingConvention.HasThis,
                        ContainingType    = this.host.PlatformType.SystemCollectionsGenericIEnumerable,
                        InternFactory     = this.host.InternFactory,
                        Name       = this.host.NameTable.GetNameFor("GetEnumerator"),
                        Parameters = new List <IParameterTypeInformation>(),
                        Type       = this.host.PlatformType.SystemCollectionsGenericIEnumerator,
                    },
                };
                var getEnumerator2 = (IMethodReference)
                                     IteratorHelper.First(genericEnumerableType.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("GetEnumerator"), false));
                getEnumerator = getEnumerator2;
                getCurrent    = (IMethodReference)IteratorHelper.First(genericEnumeratorType.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false));
            }
            else
            {
                enumeratorType = this.host.PlatformType.SystemCollectionsIEnumerator;
                getEnumerator  = new MethodReference()
                {
                    CallingConvention = CallingConvention.HasThis,
                    ContainingType    = enumeratorType,
                    InternFactory     = this.host.InternFactory,
                    Name       = this.host.NameTable.GetNameFor("GetEnumerator"),
                    Parameters = new List <IParameterTypeInformation>(),
                    Type       = this.host.PlatformType.SystemCollectionsIEnumerable,
                };
                getCurrent = new MethodReference()
                {
                    CallingConvention = CallingConvention.HasThis,
                    ContainingType    = enumeratorType,
                    InternFactory     = this.host.InternFactory,
                    Name       = this.host.NameTable.GetNameFor("get_Current"),
                    Parameters = new List <IParameterTypeInformation>(),
                    Type       = this.host.PlatformType.SystemObject,
                };
            }

            var initializer = new MethodCall()
            {
                Arguments     = new List <IExpression>(),
                IsStaticCall  = false,
                IsVirtualCall = true,
                MethodToCall  = getEnumerator,
                ThisArgument  = forEachStatement.Collection,
                Type          = enumeratorType,
            };
            IStatement initialization;

            if (!this.foreachLocals.TryGetValue(key, out foreachLocal))
            {
                foreachLocal = new LocalDefinition()
                {
                    Type = enumeratorType, Name = this.host.NameTable.GetNameFor("CS$5$" + this.foreachLocals.Count)
                };
                this.foreachLocals.Add(key, foreachLocal);
                initialization = new LocalDeclarationStatement()
                {
                    InitialValue  = initializer,
                    LocalVariable = foreachLocal,
                };
            }
            else
            {
                initialization = new ExpressionStatement()
                {
                    Expression = new Assignment()
                    {
                        Source = initializer,
                        Target = new TargetExpression()
                        {
                            Definition = foreachLocal,
                            Instance   = null,
                            Type       = foreachLocal.Type,
                        },
                        Type = foreachLocal.Type,
                    },
                };
            }

            var newStmts = new List <IStatement>();

            newStmts.Add(new ExpressionStatement()
            {
                Expression = new Assignment()
                {
                    Source = new MethodCall()
                    {
                        Arguments     = new List <IExpression>(),
                        IsStaticCall  = false,
                        IsVirtualCall = true,
                        MethodToCall  = getCurrent,
                        ThisArgument  = new BoundExpression()
                        {
                            Definition = foreachLocal,
                            Instance   = null,
                        },
                        Type = forEachStatement.Variable.Type,
                    },
                    Target = new TargetExpression()
                    {
                        Definition = forEachStatement.Variable,
                        Instance   = null,
                    },
                    Type = forEachStatement.Variable.Type,
                },
            });
            newStmts.Add(forEachStatement.Body);
            var newBody = new BlockStatement()
            {
                Statements = newStmts,
            };
            var result = new BlockStatement()
            {
                Statements = new List <IStatement>()
                {
                    initialization,
                    new TryCatchFinallyStatement()
                    {
                        TryBody = new BlockStatement()
                        {
                            Statements = new List <IStatement>()
                            {
                                new WhileDoStatement()
                                {
                                    Body      = newBody,
                                    Condition = new MethodCall()
                                    {
                                        Arguments     = new List <IExpression>(),
                                        IsStaticCall  = false,
                                        IsVirtualCall = true,
                                        MethodToCall  = moveNext,
                                        ThisArgument  = new BoundExpression()
                                        {
                                            Definition = foreachLocal,
                                            Instance   = null,
                                        },
                                        Type = this.host.PlatformType.SystemBoolean,
                                    },
                                },
                            },
                        },
                        FinallyBody = new BlockStatement()
                        {
                            Statements = new List <IStatement>()
                            {
                                new ConditionalStatement()
                                {
                                    Condition = new Equality()
                                    {
                                        LeftOperand = new BoundExpression()
                                        {
                                            Definition = foreachLocal, Instance = null, Type = foreachLocal.Type,
                                        },
                                        RightOperand = new CompileTimeConstant()
                                        {
                                            Type = foreachLocal.Type, Value = null,
                                        },
                                        Type = this.host.PlatformType.SystemBoolean,
                                    },
                                    FalseBranch = new EmptyStatement(),
                                    TrueBranch  = new ExpressionStatement()
                                    {
                                        Expression = new MethodCall()
                                        {
                                            Arguments     = new List <IExpression>(),
                                            IsStaticCall  = false,
                                            IsVirtualCall = true,
                                            MethodToCall  = this.disposeMethod,
                                            ThisArgument  = new BoundExpression()
                                            {
                                                Definition = foreachLocal,
                                                Instance   = null,
                                            },
                                            Type = this.host.PlatformType.SystemVoid,
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            };

            return(result);
        }
Пример #32
0
        private void addOpaquePredicatesIter(CfgManipulator cfgManipulator, GraphRandomStateGenerator randomStateGenerator, MethodCfg originalMethodCfg, MethodCfg methodCfg, BasicBlock startBasicBlock, LocalDefinition intStateLocal, LocalDefinition currentNodeLocal) {

            // create a list of basic blocks that still have to be processed by the algorithm
            List<BasicBlock> basicBlocksToProcess = new List<BasicBlock>(methodCfg.basicBlocks);

            System.Console.WriteLine("Basic Blocks to process (Opaque Predicates): " + basicBlocksToProcess.Count());

            while (true) {

                List<BasicBlock> copiedList = new List<BasicBlock>(basicBlocksToProcess);
                foreach (BasicBlock currentBasicBlock in copiedList) {

                    // process all entry branches of the current basic block
                    List<IBranchTarget> copiedBranchList = new List<IBranchTarget>(currentBasicBlock.entryBranches);
                    foreach (IBranchTarget entryBranch in copiedBranchList) {

                        // get the metadata for the source basic block of the entry branch
                        BasicBlock sourceBasicBlock = entryBranch.sourceBasicBlock;
                        IGraphTransformerMetadata sourceMetadata = null;
                        for (int i = 0; i < sourceBasicBlock.transformationMetadata.Count(); i++) {
                            // get graph transformer metadata for basic blocks
                            if ((sourceBasicBlock.transformationMetadata.ElementAt(i) as IGraphTransformerMetadata) == null) {
                                continue;
                            }
                            sourceMetadata = (sourceBasicBlock.transformationMetadata.ElementAt(i) as IGraphTransformerMetadata);
                            break;
                        }
                        if (sourceMetadata == null) {
                            throw new ArgumentException("Not able to find metadata for source basic block of the entry branch.");
                        }

                        // only process entry branches with only one link to the obfuscation graph
                        if (sourceMetadata.correspondingGraphNodes.Count() != 1) {
                            continue;
                        }

                        // check if the source basic block is a basic block that moves the pointer to the obfuscation graph
                        // => use the link from the current basic block to the obfuscation graph
                        BasicBlockGraphNodeLink link = null;
                        if ((sourceMetadata as GraphTransformerNextNodeBasicBlock) != null) {

                            // get the metadata for the current basic block (because the source basic block has moved the pointer to the obfuscation graph)
                            IGraphTransformerMetadata currentMetadata = null;
                            for (int i = 0; i < currentBasicBlock.transformationMetadata.Count(); i++) {
                                // get graph transformer metadata for basic blocks
                                if ((currentBasicBlock.transformationMetadata.ElementAt(i) as IGraphTransformerMetadata) == null) {
                                    continue;
                                }
                                currentMetadata = (currentBasicBlock.transformationMetadata.ElementAt(i) as IGraphTransformerMetadata);
                                break;
                            }
                            if (currentMetadata == null) {
                                throw new ArgumentException("Not able to find metadata for source basic block of the entry branch.");
                            }

                            // when current basic block also moves the pointer to the obfuscation graph => skip opaque predicate insertion it (for the moment)
                            // (problem with obfuscation graph nodes that do not reside on the vpath because of pointer correction code)
                            if ((currentMetadata as GraphTransformerNextNodeBasicBlock) != null) {
                                continue;
                            }

                            // get the link to the correct obfuscation graph node for the valid path that goes through the source basic block
                            BasicBlockGraphNodeLink sourceLink = sourceMetadata.correspondingGraphNodes.ElementAt(0);
                            foreach (BasicBlockGraphNodeLink tempLink in currentMetadata.correspondingGraphNodes) {
                                if (tempLink.validPathId == sourceLink.validPathId) {
                                    link = tempLink;
                                }
                            }
                            if (link == null) {
                                throw new ArgumentException("Not able to find link from current basic block to the obfuscation graph.");
                            }

                        }

                        // => just use the link from the source basic block to the obfuscation graph
                        else {
                            link = sourceMetadata.correspondingGraphNodes.ElementAt(0);
                        }

                        // decide randomly to add an opaque predicate
                        switch (this.prng.Next(this.insertOpaquePredicateWeight)) {
                            case 0:
                            case 1:
                            case 2:
                            case 3:
                            case 4:
                            case 5: {

                                    // choose randomly which opaque predicate should be added
                                    int opaquePredicate = this.prng.Next(2);
                                    this.injectOpaquePredicateCode(cfgManipulator, methodCfg, currentBasicBlock, entryBranch, link, opaquePredicate, currentNodeLocal);

                                    break;
                                }

                            default: {
                                    break;
                                }
                        }

                    }

                    // remove currently processed basic block from the list of basic blocks to process
                    basicBlocksToProcess.Remove(currentBasicBlock);

                }

                System.Console.WriteLine("Basic Blocks to process (Opaque Predicates): " + basicBlocksToProcess.Count());

                // check if basic blocks exist to process => if not break loop
                if (basicBlocksToProcess.Count() == 0) {
                    break;
                }

            }

        }
      protected override void RewriteStoreField(IOperation op) {

        var fieldReference = op.Value as IFieldReference;
        Contract.Assert(fieldReference != null);

        if (fieldReference.ContainingType.IsEnum == false) {
          var storeFieldCounter = new FieldReference() {
            Name = base.host.NameTable.GetNameFor(MemberHelper.GetMemberSignature(fieldReference, NameFormattingOptions.None) + "$$storeCount"),
            Type = base.host.PlatformType.SystemInt64,
            InternFactory = base.host.InternFactory,
            ContainingType = fieldReference.ContainingType,
            IsStatic = false
          };

          // save the variable that is on the top of stack
          var name = "XXX_" + fieldReference.Name.ToString();
          var def = new LocalDefinition {
            Name = base.host.NameTable.GetNameFor(name),
            Type = fieldReference.Type
          };
          if (base.methodBody.LocalVariables == null) base.methodBody.LocalVariables = new List<ILocalDefinition>(1);
          base.methodBody.LocalVariables.Add(def);

          // store top-of-stack into a local.  This is the value the stfld uses
          generator.Emit(OperationCode.Stloc, def);

          base.generator.Emit(OperationCode.Dup);  // load "this" onto stack
          base.generator.Emit(OperationCode.Dup); // load "this" onto stack
          base.generator.Emit(OperationCode.Ldfld, storeFieldCounter); // load field$$storeCount onto stack
          base.generator.Emit(OperationCode.Ldc_I4_1); // load 1 onto stack
          base.generator.Emit(OperationCode.Conv_I8);  // convert to int64
          base.generator.Emit(OperationCode.Add);      // add field$storeCount + 1            
          base.generator.Emit(OperationCode.Stfld, storeFieldCounter); // store result of add to field$$storeCount

          // restore the var we saved from the local
          generator.Emit(OperationCode.Ldloc, def);
        }

        // now do the original stfld
        base.RewriteStoreField(op);
      }
Пример #34
0
        private ILocalDefinition ExtractExceptionContainer(DecompiledBlock nestedBlock, ITypeReference exceptionType)
        {
            Contract.Requires(nestedBlock != null);
            Contract.Requires(exceptionType != null);
            Contract.Ensures(Contract.Result <ILocalDefinition>() != null);

            Contract.Assume(nestedBlock.Statements.Count > 0);
            int i = 0;

            while (nestedBlock.Statements[i] is LocalDeclarationStatement)
            {
                i++; Contract.Assume(i < nestedBlock.Statements.Count);
            }
            ;
            var firstStatement = nestedBlock.Statements[i++];
            var firstBlock     = firstStatement as DecompiledBlock;

            while (firstBlock != null)
            {
                Contract.Assume(firstBlock.Statements.Count > 0);
                i = 0;
                while (firstBlock.Statements[i] is LocalDeclarationStatement)
                {
                    i++; Contract.Assume(i < firstBlock.Statements.Count);
                }
                ;
                firstStatement = firstBlock.Statements[i++];
                nestedBlock    = firstBlock;
                firstBlock     = firstStatement as DecompiledBlock;
            }
            //Ignoring any local declarations inserted for lexical scopes, any decompiled block that does not start with a nested block, starts with a label.
            Contract.Assume(firstStatement is LabeledStatement);
            if (nestedBlock.Statements.Count > i)
            {
                var exprStatement = nestedBlock.Statements[i] as ExpressionStatement;
                if (exprStatement != null)
                {
                    nestedBlock.Statements.RemoveRange(i - 1, 2);
                    if (exprStatement.Expression is PopValue)
                    {
                        return(Dummy.LocalVariable);
                    }
                    var assignment = exprStatement.Expression as Assignment;
                    if (assignment != null && assignment.Source is PopValue)
                    {
                        var local = assignment.Target.Definition as ILocalDefinition;
                        if (local != null)
                        {
                            return(local);   //if not, this is not a recognized code pattern.
                        }
                    }
                }
                // can't find the local, so just introduce one and leave its value on the stack
                var ld = new LocalDefinition()
                {
                    Type = exceptionType,
                };
                var pushStatement = new PushStatement()
                {
                    ValueToPush = new BoundExpression()
                    {
                        Definition = ld,
                        Type       = exceptionType,
                    },
                };
                nestedBlock.Statements.Insert(0, pushStatement);
                return(ld);
            }
            else
            {
                //Valid IL should always have at least one instruction to consume the exception value as well as a branch out of the handler block.
                Contract.Assume(false);
                return(Dummy.LocalVariable);
            }
        }
Пример #35
0
 /// <summary>
 /// The source expression "new C(){ f1 = e1, f2 = e2, ... }" (where the f's can be fields
 /// or properties) turns into "cgl = new C(); cgl.f1 = e1; cg1.f2 = e2; ...".
 /// ("cgl" means "compiler-generated local".)
 /// Turn it into a block expression whose Statements are the statements above (but where
 /// the first one becomes a local declaration statement), and with an Expression that is
 /// just the local, cgl', where cgl' is a freshly created local.
 /// </summary>
 private bool ReplaceCompilerGeneratedLocalUsedForInitializersPattern(BlockStatement b) {
   Contract.Requires(b != null);
   bool replacedPattern = false;
   var statements = b.Statements;
   for (int i = 0; i < statements.Count - 1; i++) {
     var expressionStatement = statements[i] as ExpressionStatement;
     if (expressionStatement == null) continue;
     var assignment = expressionStatement.Expression as Assignment;
     if (assignment == null) continue;
     var local = assignment.Target.Definition as ILocalDefinition;
     if (local == null || local is CapturedLocalDefinition) continue;
     if (this.numberOfAssignmentsToLocal[local] != 1) continue;
     if (this.sourceLocationProvider != null) {
       bool isCompilerGenerated;
       var sourceName = this.sourceLocationProvider.GetSourceNameFor(local, out isCompilerGenerated);
       if (!isCompilerGenerated) continue;
     }
     var createObject = assignment.Source as ICreateObjectInstance;
     if (createObject == null) continue;
     if (!this.singleUseExpressionChecker.ExpressionCanBeMovedAndDoesNotReference(assignment.Source, local)) continue;
     var j = 1;
     while (i + j < statements.Count - 1 && IsAssignmentToFieldOrProperty(local, statements[i + j])) j++;
     if (j == 1) continue;
     if (this.numberOfReferencesToLocal[local] != (uint)j) continue;
     Contract.Assume(i + j < statements.Count); //i < statements.Count-1 and (j == 1 or the loop above established i+j < statements.Count-1)
     Contract.Assume(statements[i + j] != null);
     if (LocalFinder.LocalOccursIn(statements[i+j], local) && this.singleAssignmentReferenceFinder.LocalCanBeReplacedIn(statements[i + j], local)) {
       var newLocal = new LocalDefinition() {
         Name = this.host.NameTable.GetNameFor(local.Name.Value + "_prime"),
         MethodDefinition = local.MethodDefinition,
         Type = local.Type,
       };
       var lds = new LocalDeclarationStatement() {
         InitialValue = assignment.Source,
         LocalVariable = newLocal,
       };
       var stmts = new List<IStatement>(j) { lds, };
       var boundExpression = new BoundExpression() { Definition = newLocal, Instance = null, Type = newLocal.Type, };
       foreach (var s in statements.GetRange(i + 1, j - 1)) {
         Contract.Assume(s != null);
         this.singleAssignmentLocalReplacer.Replace(boundExpression, local, s);
         stmts.Add(s);
       }
       var blockExpression = new BlockExpression() {
         BlockStatement = new BlockStatement() {
           Statements = stmts,
         },
         Expression = new BoundExpression() { Definition = newLocal, Instance = null, Type = newLocal.Type, },
         Type = newLocal.Type,
       };
       if (this.singleAssignmentLocalReplacer.Replace(blockExpression, local, statements[i + j])) {
         this.numberOfAssignmentsToLocal[newLocal] = 1;
         this.numberOfReferencesToLocal[newLocal] = (uint)j;
         this.numberOfAssignmentsToLocal[local]--;
         this.numberOfReferencesToLocal[local] = 0;
         statements.RemoveRange(i, j);
         replacedPattern = true;
       } else
         Contract.Assume(false); // replacement should succeed since the combination of LocalOccursIn and LocalCanBeReplacedIn returned true
     }
   }
   return replacedPattern;
 }
Пример #36
0
 public override ILocalDefinition Rewrite(ILocalDefinition localDefinition) {
   if (localDefinition.MethodDefinition != this.moveNext) // might happen to visit an already replaced local
     return localDefinition;
   ILocalDefinition loc;
   if (!this.localTable.TryGetValue(localDefinition, out loc)) {
     loc = new LocalDefinition() {
       MethodDefinition = this.iterator,
       Name = localDefinition.Name,
       Type = localDefinition.Type,
     };
     this.localTable.Add(localDefinition, loc);
   }
   return loc;
 }
Пример #37
0
            private void FindCapturedLocals(List<IStatement> statements)
            {
                ILocalDefinition/*?*/ locDef = null;
                IFieldReference/*?*/ fieldRef = null;
                INestedTypeReference/*?*/ closureType = null;
                int i = 0;
                while (i < statements.Count && closureType == null) {
                  var statement = statements[i++];
                  var locDecl = statement as LocalDeclarationStatement;
                  if (locDecl == null) {
                var exprStatement = statement as ExpressionStatement;
                if (exprStatement == null) continue;
                var assignment = exprStatement.Expression as Assignment;
                if (assignment == null) continue;
                if (!(assignment.Source is ICreateObjectInstance)) continue;
                locDef = assignment.Target.Definition as ILocalDefinition;
                if (locDef != null)
                  closureType = UnspecializedMethods.AsUnspecializedNestedTypeReference(locDef.Type);
                else {
                  fieldRef = assignment.Target.Definition as IFieldReference;
                  if (fieldRef == null || !(assignment.Target.Instance is IThisReference)) continue;
                  closureType = UnspecializedMethods.AsUnspecializedNestedTypeReference(fieldRef.Type);
                }
                  } else {
                if (!(locDecl.InitialValue is ICreateObjectInstance)) continue;
                locDef = locDecl.LocalVariable;
                closureType = UnspecializedMethods.AsUnspecializedNestedTypeReference(locDef.Type);
                  }
                }
                if (closureType == null) return;
                //REVIEW: need to avoid resolving types that are not defined in the module we are analyzing.
                ITypeReference t1 = UnspecializedMethods.AsUnspecializedTypeReference(closureType.ContainingType.ResolvedType);
                ITypeReference t2 = UnspecializedMethods.AsUnspecializedTypeReference(this.remover.containingType);
                if (!TypeHelper.TypesAreEquivalent(t1, t2)) {
                  var nt2 = t2 as INestedTypeReference;
                  if (nt2 == null || !TypeHelper.TypesAreEquivalent(t1, nt2.ContainingType)) return;
                }
                var resolvedClosureType = closureType.ResolvedType;
                if (!UnspecializedMethods.IsCompilerGenerated(resolvedClosureType)) return;
                //Check if this is an iterator creating its state class, rather than just a method creating a closure class
                foreach (var iface in resolvedClosureType.Interfaces) {
                  if (TypeHelper.TypesAreEquivalent(iface, resolvedClosureType.PlatformType.SystemCollectionsIEnumerator)) return;
                }
                if (this.remover.sourceMethodBody.privateHelperTypesToRemove == null)
                  this.remover.sourceMethodBody.privateHelperTypesToRemove = new List<ITypeDefinition>();
                this.remover.sourceMethodBody.privateHelperTypesToRemove.Add(resolvedClosureType);
                if (locDef != null)
                  this.remover.currentClosureLocals.Add(locDef, true);
                else {
                  if (this.remover.sourceMethodBody.privateHelperFieldsToRemove == null)
                this.remover.sourceMethodBody.privateHelperFieldsToRemove = new Dictionary<IFieldDefinition, IFieldDefinition>();
                  var field = UnspecializedMethods.UnspecializedFieldDefinition(fieldRef.ResolvedField);
                  this.remover.sourceMethodBody.privateHelperFieldsToRemove.Add(field, field);
                }

                if (resolvedClosureType.IsGeneric && this.remover.sourceMethodBody.MethodDefinition.IsGeneric)
                  this.remover.genericParameterMapper = new GenericMethodParameterMapper(this.remover.host, this.remover.sourceMethodBody.MethodDefinition, resolvedClosureType);

                statements.RemoveAt(i - 1);

                // Walk the rest of the statements in the block (but *without* recursively
                // descending into them) looking for assignments that save local state into
                // fields in the closure. Such assignments do not belong in the method body.
                //
                // They were introduced by the compiler because the closure reads their value.
                // That is, such assignments are of the form:
                //  closureLocal.f := e
                // where "e" is either "this", a local, a parameter, (corner case) a value not held in a local of the original program,
                // or another closureLocal (because sometimes the compiler generates code so
                // that one closure class has access to another one).
                // When the RHS expression is a local/parameter, then rely on a naming
                // convention that the field f has the same name as the local/parameter.
                // If it does not follow the naming convention, then the statement corresponds to
                // a real statement that was in the original method body.
                //
                // For each such assignment statement, delete it from the list of statements and
                // add "e" to the remover's table as the expression to replace all occurrences of
                // "closureLocal.f" throughout the method body.
                //
                // [Note on corner case: this seems to arise when a value occurs in an anonymous delegate that
                // isn't used outside of the anonymous delegate.
                // For instance: { ... var x = new Object(); M((args for lambda) => ... body of lambda contains a reference to x ...) ... }
                // where there are no occurrences of x in the rest of the method body. The compiler plays it safe and still treats x as a
                // captured local.]
                //
                for (int j = i - 1; j < statements.Count; j++) {
                  if (statements[j] is IEmptyStatement) continue;
                  IExpressionStatement/*?*/ es = statements[j] as IExpressionStatement;
                  if (es == null) continue;
                  IAssignment/*?*/ assignment = es.Expression as IAssignment;
                  if (assignment == null) continue;
                  IFieldReference/*?*/ closureField = assignment.Target.Definition as IFieldReference;
                  if (closureField == null) {
                // check to see if it is of the form "loc := closureLocal".
                // I.e., a local has been introduced that is an alias for a local containing a closure instance.
                var targetLoc = this.TargetExpressionAsLocal(assignment.Target);
                var sourceLoc = this.ExpressionAsLocal(assignment.Source);
                if (targetLoc != null && sourceLoc != null && this.remover.currentClosureLocals.ContainsKey(sourceLoc)) {
                  this.remover.currentClosureLocals.Add(targetLoc, true);
                  statements.RemoveAt(j--);
                }
                continue;
                  }
                  var unspecializedClosureField = UnspecializedMethods.UnspecializedFieldReference(closureField);
                  var closureFieldContainingType = UnspecializedMethods.AsUnspecializedNestedTypeReference(closureField.ContainingType);
                  if (closureFieldContainingType == null) continue;
                  if (!TypeHelper.TypesAreEquivalent(closureFieldContainingType, closureType)) continue;
                  if (this.remover.capturedBinding.ContainsKey(unspecializedClosureField.InternedKey)) continue;
                  var thisReference = assignment.Source as IThisReference;
                  if (thisReference == null) {
                var/*?*/ binding = assignment.Source as IBoundExpression;
                //if (binding == null) {
                //  //The closure is capturing a local that is defined in the block being closed over. Need to introduce the local.
                //  var newLocal = new LocalDefinition() {
                //    Name = closureField.Name,
                //    Type = closureField.Type,
                //  };
                //  var newLocalDecl = new LocalDeclarationStatement() { LocalVariable = newLocal, InitialValue = assignment.Source };
                //  statements[j] = newLocalDecl;
                //  if (this.remover.sourceMethodBody.privateHelperFieldsToRemove == null)
                //    this.remover.sourceMethodBody.privateHelperFieldsToRemove = new Dictionary<IFieldDefinition, IFieldDefinition>();
                //  this.remover.sourceMethodBody.privateHelperFieldsToRemove[unspecializedClosureField.ResolvedField] = unspecializedClosureField.ResolvedField;
                //  this.remover.capturedBinding.Add(unspecializedClosureField.InternedKey, new BoundExpression() { Definition = newLocal, Type = newLocal.Type });
                //  continue;
                //}
                if (binding != null && (binding.Definition is IParameterDefinition || binding.Definition is ILocalDefinition)) {
                  var p = binding.Definition as IParameterDefinition;
                  if (p != null) {
                if (closureField.Name != p.Name) {
                  continue;
                } else {
                  this.remover.capturedBinding[unspecializedClosureField.InternedKey] = binding;
                }
                  } else {
                // must be a local
                var l = binding.Definition as ILocalDefinition;
                if (closureField.Name != l.Name) {
                  // Check to see if it is closureLocal.f := other_closure_local
                  // If so, delete it.
                  var sourceLoc = ExpressionAsLocal(assignment.Source);
                  if (sourceLoc != null && (this.remover.currentClosureLocals.ContainsKey(sourceLoc) || this.exceptionContainer == sourceLoc)) {
                    statements.RemoveAt(j--);
                    if (this.exceptionContainer == sourceLoc)
                      this.remover.capturedBinding[unspecializedClosureField.InternedKey] = binding;
                  }
                  continue;
                } else {
                  this.remover.capturedBinding[unspecializedClosureField.InternedKey] = binding;
                }
                  }
                } else if (binding != null && fieldRef != null) {
                  //In this case the closure is inside an iterator and its closure fields get their values from iterator state class fields or expressions.
                  //In the former case, arrange for all references to the closure field to become references to the corresponding iterator state field.
                  //In the latter case, the loop below will introduce a local to hold the value of the expression and arrange for references to the closure
                  //field to become a reference to the local.
                  IFieldReference iteratorField = binding.Definition as IFieldReference;
                  if (iteratorField != null && binding.Instance is IThisReference) {
                this.remover.capturedBinding[unspecializedClosureField.InternedKey] = binding;
                  } else
                continue;
                } else if (binding != null) {
                  //In this case the closure is inside another closure and the closure fields get their values from the fields of the outer closure.
                  IFieldReference outerClosureField = binding.Definition as IFieldReference;
                  if (outerClosureField != null && binding.Instance is IThisReference) {
                this.remover.capturedBinding[unspecializedClosureField.InternedKey] = binding;
                  } else
                continue;
                } else {
                  // Corner case: see note above
                  LocalDefinition localDefinition = new LocalDefinition() {
                Name = closureField.ResolvedField.Name,
                Type = this.remover.genericParameterMapper == null ? closureField.Type : this.remover.genericParameterMapper.Visit(closureField.Type),
                  };
                  LocalDeclarationStatement localDeclStatement = new LocalDeclarationStatement() {
                LocalVariable = localDefinition,
                InitialValue = assignment.Source,
                  };
                  statements.Insert(j, localDeclStatement); j++;
                  this.remover.capturedBinding[unspecializedClosureField.InternedKey] = new BoundExpression() { Definition = localDefinition };
                  if (this.remover.sourceMethodBody.privateHelperFieldsToRemove == null)
                this.remover.sourceMethodBody.privateHelperFieldsToRemove = new Dictionary<IFieldDefinition, IFieldDefinition>();
                  this.remover.sourceMethodBody.privateHelperFieldsToRemove[closureField.ResolvedField] = closureField.ResolvedField;
                }
                  } else {
                this.remover.capturedBinding[unspecializedClosureField.InternedKey] = new BoundExpression() { Instance = thisReference };
                  }
                  statements.RemoveAt(j--);
                }

                foreach (var field in closureType.ResolvedType.Fields) {
                  if (this.remover.capturedBinding.ContainsKey(field.InternedKey)) continue;
                  var newLocal = new LocalDefinition() {
                Name = field.Name,
                Type = this.remover.genericParameterMapper == null ? field.Type : this.remover.genericParameterMapper.Visit(field.Type),
                  };
                  var newLocalDecl = new LocalDeclarationStatement() { LocalVariable = newLocal };
                  statements.Insert(i - 1, newLocalDecl);
                  if (this.remover.sourceMethodBody.privateHelperFieldsToRemove == null)
                this.remover.sourceMethodBody.privateHelperFieldsToRemove = new Dictionary<IFieldDefinition, IFieldDefinition>();
                  this.remover.sourceMethodBody.privateHelperFieldsToRemove[field] = field;
                  this.remover.capturedBinding.Add(field.InternedKey, new BoundExpression() { Definition = newLocal, Type = newLocal.Type });
                }
            }
Пример #38
0
 private ILocalDefinition PossiblyReplaceLocal(ILocalDefinition localDefinition) {
   ILocalDefinition localToUse;
   if (!this.tableForLocalDefinition.TryGetValue(localDefinition, out localToUse)) {
     localToUse = new LocalDefinition() {
       MethodDefinition = localDefinition.MethodDefinition,
       Name = this.host.NameTable.GetNameFor("loc" + counter),
       Type = localDefinition.Type,
     };
     this.counter++;
     this.tableForLocalDefinition.Add(localDefinition, localToUse);
     this.tableForLocalDefinition.Add(localToUse, localToUse); // in case it gets encountered again
     this.localDeclarations.Add(
       new LocalDeclarationStatement() {
         InitialValue = null,
         LocalVariable = localToUse,
       });
   }
   return localToUse ?? localDefinition;
 }
Пример #39
0
        private ILocalDefinition GetOrCreateLocal(int depth, ITypeReference type)
        {
            Contract.Requires(0 <= depth);
            Contract.Requires(type != null);

            ILocalDefinition local;
            var key = KeyForLocal(depth, type);
            if (this.createdLocals.TryGetValue(key, out local)) return local;
            local = new LocalDefinition()
            {
                Name = this.host.NameTable.GetNameFor(NameForLocal(depth, type)),
                MethodDefinition = this.methodDefinition,
                Type = type,
            };
            this.createdLocals.Add(key, local);
            return local;
        }
        public override IExpression VisitPostfixUnaryExpression(PostfixUnaryExpressionSyntax node)
        {
            var e = this.Visit(node.Operand);

            switch (node.OperatorToken.Kind)
            {
            case SyntaxKind.MinusMinusToken:
            case SyntaxKind.PlusPlusToken:
                var stmts = new List <IStatement>();
                var temp  = new LocalDefinition()
                {
                    MethodDefinition = this.method,
                    Name             = this.host.NameTable.GetNameFor("__temp" + LocalNumber()),
                    Type             = e.Type,
                };
                stmts.Add(
                    new LocalDeclarationStatement()
                {
                    InitialValue  = e,
                    LocalVariable = temp,
                });

                BinaryOperation bo;
                if (node.OperatorToken.Kind == SyntaxKind.MinusMinusToken)
                {
                    bo = new Subtraction();
                }
                else
                {
                    bo = new Addition();
                }
                object one = GetConstantOneOfMatchingTypeForIncrementDecrement(e.Type.ResolvedType); // REVIEW: Do we really need to resolve?
                bo.LeftOperand  = e;
                bo.RightOperand = new CompileTimeConstant()
                {
                    Type = e.Type, Value = one,
                };
                bo.Type = e.Type;
                var assign = new Assignment()
                {
                    Source = bo,
                    Target = Helper.MakeTargetExpression(e),
                    Type   = e.Type,
                };
                stmts.Add(
                    new ExpressionStatement()
                {
                    Expression = assign,
                });
                var blockExpression = new BlockExpression()
                {
                    BlockStatement = new BlockStatement()
                    {
                        Statements = stmts,
                    },
                    Expression = new BoundExpression()
                    {
                        Definition = temp, Instance = null, Type = temp.Type
                    },
                    Type = e.Type,
                };

                return(blockExpression);

            default:
                throw new InvalidDataException("VisitPostfixUnaryExpression: unknown operator token '" + node.OperatorToken.ValueText);
            }
        }
        public IEnumerable <IPrimarySourceLocation> GetPrimarySourceLocationsForDefinitionOf(ILocalDefinition localDefinition)
        {
            LocalDefinition locDef = localDefinition as LocalDefinition;

            return(Enumerable <IPrimarySourceLocation> .Empty);
        }
    /// <summary>
    /// When given a method definition and a block of statements that represents the Block property of the body of the method
    /// this method returns a semantically equivalent SourceMethod with a body that no longer has any anonymous delegate expressions.
    /// The given block of statements is mutated in place.
    /// Any types that get defined in order to implement the body semantics are returned (null if no such types are defined).
    /// </summary>
    /// <param name="method">The method containing the block that is to be rewritten.</param>
    /// <param name="body">The block to be rewritten. 
    /// The entire tree rooted at the block must be mutable and the nodes must not be shared with anything else.</param>
    public ICollection<ITypeDefinition>/*?*/ RemoveAnonymousDelegates(IMethodDefinition method, BlockStatement body) {
      this.method = method;
      var finder = new CapturedParameterAndLocalFinder();
      finder.TraverseChildren(body);
      this.fieldReferencesForUseInsideAnonymousMethods = finder.captures;
      this.anonymousDelegatesThatCaptureLocalsOrParameters = finder.anonymousDelegatesThatCaptureLocalsOrParameters;
      this.anonymousDelegatesThatCaptureThis = finder.anonymousDelegatesThatCaptureThis;
      finder = null;
      var blockFinder = new ScopesWithCapturedLocalsFinder(this.fieldReferencesForUseInsideAnonymousMethods);
      blockFinder.TraverseChildren(body);
      this.scopesWithCapturedLocals = blockFinder.scopesWithCapturedLocals;
      blockFinder = null;
      this.fieldReferencesForUseInsideThisMethod = new Dictionary<object, IFieldReference>(this.fieldReferencesForUseInsideAnonymousMethods);

      this.GenerateTopLevelClosure();
      if (this.currentClosureClass != null) {
        //declare a local to keep the parameter closure class
        var closureLocal = new LocalDefinition() { Type = this.currentClosureInstance, Name = this.host.NameTable.GetNameFor("CS$<>8__locals"+this.closureClasses.Count) };
        this.currentClosureLocal = closureLocal;
        this.currentClosureObject = new BoundExpression() { Definition = closureLocal, Type = closureLocal.Type };
        this.closureLocalInstances = new List<IExpression>();
        this.closureLocalInstances.Add(this.currentClosureObject);
        this.scopesWithCapturedLocals.Remove(body); //otherwise it will introduce its own closure class if any of its locals were captured.
        this.RewriteChildren(body);
        //do this after rewriting so that parameter references are not rewritten into closure field references.
        this.InsertStatementsToAllocateAndInitializeTopLevelClosure(body);
      } else {
        this.RewriteChildren(body);
      }
      return this.closureClasses == null ? null : this.closureClasses.AsReadOnly();
    }
Пример #43
0
        /// <summary />
        public override IStatement Rewrite(IForEachStatement forEachStatement)
        {
            ILocalDefinition foreachLocal;
            var key = forEachStatement.Collection.Type.InternedKey;

            ITypeReference enumeratorType;
            IMethodReference getEnumerator;
            IMethodReference getCurrent;

            var gtir = forEachStatement.Collection.Type as IGenericTypeInstanceReference;
            if (gtir != null)
            {
                var typeArguments = gtir.GenericArguments;
                ITypeReference genericEnumeratorType = new Immutable.GenericTypeInstanceReference(this.host.PlatformType.SystemCollectionsGenericIEnumerator, typeArguments, this.host.InternFactory);
                ITypeReference genericEnumerableType = new Immutable.GenericTypeInstanceReference(this.host.PlatformType.SystemCollectionsGenericIEnumerable, typeArguments, this.host.InternFactory);
                enumeratorType = genericEnumeratorType;
                getEnumerator = new SpecializedMethodReference()
                {
                    CallingConvention = CallingConvention.HasThis,
                    ContainingType = genericEnumerableType,
                    InternFactory = this.host.InternFactory,
                    Name = this.host.NameTable.GetNameFor("GetEnumerator"),
                    Parameters = new List<IParameterTypeInformation>(),
                    Type = genericEnumeratorType,
                    UnspecializedVersion = new MethodReference()
                    {
                        CallingConvention = CallingConvention.HasThis,
                        ContainingType = this.host.PlatformType.SystemCollectionsGenericIEnumerable,
                        InternFactory = this.host.InternFactory,
                        Name = this.host.NameTable.GetNameFor("GetEnumerator"),
                        Parameters = new List<IParameterTypeInformation>(),
                        Type = this.host.PlatformType.SystemCollectionsGenericIEnumerator,
                    },
                };
                var getEnumerator2 = (IMethodReference) 
                    IteratorHelper.First(genericEnumerableType.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("GetEnumerator"), false));
                getEnumerator = getEnumerator2;
                getCurrent = (IMethodReference) IteratorHelper.First(genericEnumeratorType.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false));
            }
            else
            {
                enumeratorType = this.host.PlatformType.SystemCollectionsIEnumerator;
                getEnumerator = new MethodReference()
                {
                    CallingConvention = CallingConvention.HasThis,
                    ContainingType = enumeratorType,
                    InternFactory = this.host.InternFactory,
                    Name = this.host.NameTable.GetNameFor("GetEnumerator"),
                    Parameters = new List<IParameterTypeInformation>(),
                    Type = this.host.PlatformType.SystemCollectionsIEnumerable,
                };
                getCurrent = new MethodReference()
                {
                    CallingConvention = CallingConvention.HasThis,
                    ContainingType = enumeratorType,
                    InternFactory = this.host.InternFactory,
                    Name = this.host.NameTable.GetNameFor("get_Current"),
                    Parameters = new List<IParameterTypeInformation>(),
                    Type = this.host.PlatformType.SystemObject,
                };
            }

            var initializer = new MethodCall()
                    {
                        Arguments = new List<IExpression>(),
                        IsStaticCall = false,
                        IsVirtualCall = true,
                        MethodToCall = getEnumerator,
                        ThisArgument = forEachStatement.Collection,
                        Type = enumeratorType,
                    };
            IStatement initialization;

            if (!this.foreachLocals.TryGetValue(key, out foreachLocal))
            {
                foreachLocal = new LocalDefinition() { Type = enumeratorType, Name = this.host.NameTable.GetNameFor("CS$5$" + this.foreachLocals.Count) };
                this.foreachLocals.Add(key, foreachLocal);
                initialization = new LocalDeclarationStatement()
                {
                    InitialValue = initializer,
                    LocalVariable = foreachLocal,
                };
            }
            else
            {
                initialization = new ExpressionStatement()
                {
                    Expression = new Assignment()
                    {
                        Source = initializer,
                        Target = new TargetExpression()
                        {
                            Definition = foreachLocal,
                            Instance = null,
                            Type = foreachLocal.Type,
                        },
                        Type = foreachLocal.Type,
                    },
                };
            }

            var newStmts = new List<IStatement>();
            newStmts.Add(new ExpressionStatement(){
                                                Expression = new Assignment(){
                                                     Source = new MethodCall(){
                                                          Arguments = new List<IExpression>(),
                                                          IsStaticCall = false,
                                                          IsVirtualCall = true,
                                                          MethodToCall = getCurrent,
                                                          ThisArgument = new BoundExpression(){
                                                               Definition = foreachLocal,
                                                               Instance = null,
                                                          },
                                                          Type = forEachStatement.Variable.Type,
                                                     },
                                                      Target = new TargetExpression(){
                                                           Definition = forEachStatement.Variable,
                                                           Instance = null,
                                                      },
                                                       Type = forEachStatement.Variable.Type,
                                                },
                                           });
            newStmts.Add(forEachStatement.Body);
            var newBody = new BlockStatement(){ Statements = newStmts,}; 
            var result = new BlockStatement()
            {
                Statements = new List<IStatement>(){
                   initialization,
                   new TryCatchFinallyStatement(){
                       TryBody = new BlockStatement() {
                           Statements = new List<IStatement>(){
                               new WhileDoStatement(){
                                   Body = newBody,
                                   Condition = new MethodCall(){
                                       Arguments = new List<IExpression>(),
                                       IsStaticCall = false,
                                       IsVirtualCall = true,
                                       MethodToCall = moveNext,
                                       ThisArgument = new BoundExpression(){ 
                                           Definition = foreachLocal,
                                           Instance = null,
                                       },
                                       Type = this.host.PlatformType.SystemBoolean,
                                   },
                               },
                           },
                       },
                       FinallyBody = new BlockStatement() {
                           Statements = new List<IStatement>(){
                               new ConditionalStatement(){
                                   Condition = new Equality(){
                                       LeftOperand = new BoundExpression(){ Definition = foreachLocal, Instance = null, Type = foreachLocal.Type, },
                                       RightOperand = new CompileTimeConstant(){ Type = foreachLocal.Type, Value = null, },
                                       Type = this.host.PlatformType.SystemBoolean,
                                   },
                                   FalseBranch = new EmptyStatement(),
                                   TrueBranch = new ExpressionStatement(){
                                       Expression = new MethodCall(){
                                           Arguments = new List<IExpression>(),
                                           IsStaticCall = false,
                                           IsVirtualCall = true,
                                           MethodToCall = this.disposeMethod,
                                           ThisArgument = new BoundExpression(){ 
                                               Definition = foreachLocal,
                                               Instance = null,
                                           },
                                           Type = this.host.PlatformType.SystemVoid,
                                       },
                                   },
                               },
                           },
                       },
                   },
                },
            };
            return result;
        }
 /// <summary>
 /// Rewrites the given assignment expression.
 /// </summary>
 public override IExpression Rewrite(IAssignment assignment) {
   var targetInstance = assignment.Target.Instance;
   var result = base.Rewrite(assignment);
   if (targetInstance == null && assignment.Target.Instance != null) {
     //The target now pushes something onto the stack that was not there before the rewrite.
     //It the right hand side uses the stack, then it will not see the stack it expected.
     //If so, we need to evaluate the right handside and squirrel it away in a temp before executing
     //the actual assignment.
     var popFinder = new PopFinder();
     popFinder.Traverse(assignment.Source);
     if (popFinder.foundAPop) {
       var temp = new LocalDefinition() { Name = this.host.NameTable.GetNameFor("PopTemp"+this.popTempCounter++), Type = assignment.Source.Type };
       var localDeclarationStatement = new LocalDeclarationStatement() { LocalVariable = temp, InitialValue = assignment.Source };
       var blockStatement = new BlockStatement();
       blockStatement.Statements.Add(localDeclarationStatement);
       Contract.Assume(assignment is Assignment);
       ((Assignment)assignment).Source = new BoundExpression() { Definition = temp, Type = temp.Type };
       return new BlockExpression() { BlockStatement = blockStatement, Expression = assignment, Type = assignment.Type };
     }        
   }
   return result;
 }
Пример #45
0
        internal override void Generate(CodeGenerator cg)
        {
            Debug.Assert(this.Enumeree != null);

            // get the enumerator,
            // bind actual MoveNext() and CurrentValue and CurrentKey

            // Template: using(
            // a) enumerator = enumeree.GetEnumerator()
            // b) enumerator = Operators.GetEnumerator(enumeree)
            // ) ...

            cg.EmitSequencePoint(this.Enumeree.PhpSyntax);

            var enumereeType = cg.Emit(this.Enumeree);

            Debug.Assert(enumereeType.SpecialType != SpecialType.System_Void);

            var getEnumeratorMethod = enumereeType.LookupMember <MethodSymbol>(WellKnownMemberNames.GetEnumeratorMethodName);

            TypeSymbol enumeratorType;

            if (enumereeType.IsEqualToOrDerivedFrom(cg.CoreTypes.PhpArray))
            {
                cg.Builder.EmitBoolConstant(_aliasedValues);

                // PhpArray.GetForeachtEnumerator(bool)
                enumeratorType = cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.PhpArray.GetForeachEnumerator_Boolean);
            }
            // TODO: IPhpEnumerable
            // TODO: Iterator
            else if (getEnumeratorMethod != null && getEnumeratorMethod.ParameterCount == 0 && enumereeType.IsReferenceType)
            {
                // enumeree.GetEnumerator()
                enumeratorType = cg.EmitCall(getEnumeratorMethod.IsVirtual ? ILOpCode.Callvirt : ILOpCode.Call, getEnumeratorMethod);
            }
            else
            {
                cg.EmitConvertToPhpValue(enumereeType, 0);
                cg.Builder.EmitBoolConstant(_aliasedValues);
                cg.EmitCallerRuntimeTypeHandle();

                // Operators.GetForeachEnumerator(PhpValue, bool, RuntimeTypeHandle)
                enumeratorType = cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.GetForeachEnumerator_PhpValue_Bool_RuntimeTypeHandle);
            }

            //
            _current       = enumeratorType.LookupMember <PropertySymbol>(WellKnownMemberNames.CurrentPropertyName); // TODO: Err if no Current
            _currentValue  = enumeratorType.LookupMember <PropertySymbol>(_aliasedValues ? "CurrentValueAliased" : "CurrentValue");
            _currentKey    = enumeratorType.LookupMember <PropertySymbol>("CurrentKey");
            _disposeMethod = enumeratorType.LookupMember <MethodSymbol>("Dispose", m => m.ParameterCount == 0 && !m.IsStatic);

            //
            _enumeratorLoc = cg.GetTemporaryLocal(enumeratorType);
            cg.Builder.EmitLocalStore(_enumeratorLoc);

            // bind methods
            _moveNextMethod = enumeratorType.LookupMember <MethodSymbol>(WellKnownMemberNames.MoveNextMethodName);    // TODO: Err if there is no MoveNext()
            Debug.Assert(_moveNextMethod.ReturnType.SpecialType == SpecialType.System_Boolean);
            Debug.Assert(_moveNextMethod.IsStatic == false);

            if (_disposeMethod != null)
            {
                /* Template: try { body } finally { enumerator.Dispose }
                 */

                // try {
                cg.Builder.AssertStackEmpty();
                cg.Builder.OpenLocalScope(ScopeType.TryCatchFinally);
                cg.Builder.OpenLocalScope(ScopeType.Try);

                //
                EmitBody(cg);

                // }
                cg.Builder.CloseLocalScope();   // /Try

                // finally {
                cg.Builder.OpenLocalScope(ScopeType.Finally);

                // enumerator.Dispose() & cleanup
                EmitDisposeAndClean(cg);

                // }
                cg.Builder.CloseLocalScope();   // /Finally
                cg.Builder.CloseLocalScope();   // /TryCatchFinally
            }
            else
            {
                EmitBody(cg);
                EmitDisposeAndClean(cg);
            }
        }
Пример #46
0
 public TemporaryLocalDefinition(CodeGenerator cg, LocalDefinition loc)
 {
     _cg   = cg;
     _loc  = loc;
     _type = (TypeSymbol)loc.Type;
 }
Пример #47
0
        //not defined in CLR v2.
        /// <summary>
        /// Saves the current closure fields. Allocates a new closure and updates the fields. Then calls the given delegate and
        /// restores the earlier state.
        /// </summary>
        private void AllocateClosureFor(object scope, List<IStatement> statements, Action rewriteScope)
        {
            Contract.Assume(!this.isInsideAnonymousMethod);
              var savedCurrentClosure = this.currentClosureClass;
              var savedCurrentClosureSelfInstance = this.currentClosureSelfInstance;
              var savedCurrentClosureInstance = this.currentClosureInstance;
              var savedCurrentClosureObject = this.currentClosureObject;
              var savedCurrentClosureLocal = this.currentClosureLocal;
              this.CreateClosureClass();
              IFieldReference outerClosure = null;
              if (savedCurrentClosureLocal != null) {
            this.CreateClosureField(this.currentClosureSelfInstance, savedCurrentClosureSelfInstance, savedCurrentClosureInstance, savedCurrentClosureLocal.Name.Value);
            outerClosure = this.fieldReferencesForUseInsideThisMethod[this.currentClosureSelfInstance];
              }

              var closureLocal = new LocalDefinition() { Type = this.currentClosureInstance, Name = this.host.NameTable.GetNameFor("CS$<>__locals"+this.closureClasses.Count) };
              this.currentClosureObject = new BoundExpression() { Definition = closureLocal, Type = this.currentClosureInstance };
              this.currentClosureLocal = closureLocal;
              if (this.closureLocalInstances == null) this.closureLocalInstances = new List<IExpression>();
              this.closureLocalInstances.Add(this.currentClosureObject);
              rewriteScope();
              statements.Insert(0, new ExpressionStatement() {
            Expression = new Assignment() {
              Target = new TargetExpression() { Definition = closureLocal, Type = closureLocal.Type },
              Source = new CreateObjectInstance() {
            MethodToCall = this.GetReferenceToDefaultConstructor(this.currentClosureInstance),
            Type = currentClosureSelfInstance,
              }
            }
              });
              if (outerClosure != null) {
            statements.Insert(1, new ExpressionStatement() {
              Expression = new Assignment() {
            Target = new TargetExpression() { Instance = new BoundExpression() { Definition = closureLocal }, Definition = outerClosure },
            Source = new BoundExpression() { Definition = savedCurrentClosureLocal }
              }
            });
              }
              this.currentClosureClass = savedCurrentClosure;
              this.currentClosureSelfInstance = savedCurrentClosureSelfInstance;
              this.currentClosureInstance = savedCurrentClosureInstance;
              this.currentClosureObject = savedCurrentClosureObject;
              this.currentClosureLocal = savedCurrentClosureLocal;
        }
Пример #48
0
 private ILocalDefinition GetLocalWithSourceName(ILocalDefinition localDef)
 {
     if (this.sourceLocationProvider == null) return localDef;
       var mutableLocal = this.localMap[localDef];
       if (mutableLocal != null) return mutableLocal;
       mutableLocal = localDef as LocalDefinition;
       if (mutableLocal == null) {
     mutableLocal = new LocalDefinition();
     mutableLocal.Copy(localDef, this.host.InternFactory);
       }
       this.localMap.Add(localDef, mutableLocal);
       bool isCompilerGenerated;
       var sourceName = this.sourceLocationProvider.GetSourceNameFor(localDef, out isCompilerGenerated);
       if (sourceName != localDef.Name.Value) {
     mutableLocal.Name = this.host.NameTable.GetNameFor(sourceName);
       }
       return mutableLocal;
 }
Пример #49
0
        private static void AddExecCommandSTS(CacheFile cache, SourceFileDefinition mySourceFile)
        {
            var gameInstanceNative = cache.GetNative("GameInstance");
            var stringNative       = cache.GetNative("String");

            var inkMenuInstanceSwitchToScenarioClass = cache.GetClass("inkMenuInstance_SwitchToScenario");

            /* Add a new definition for a native inkMenuInstance_SwitchToScenario since it doesn't exist
             * in the cache by default. It is actually defined by the game but none of the existing game
             * code uses it, so it's missing.
             */
            var inkMenuInstanceSwitchToScenario = new NativeDefinition()
            {
                Name       = "inkMenuInstance_SwitchToScenario",
                NativeType = NativeType.Complex,
            };

            cache.Definitions.Add(inkMenuInstanceSwitchToScenario);

            // Add a new ref native for the previous native.
            var inkMenuInstanceSwitchToScenarioRef = new NativeDefinition()
            {
                Name       = "ref:inkMenuInstance_SwitchToScenario",
                NativeType = NativeType.Handle,
                BaseType   = inkMenuInstanceSwitchToScenario,
            };

            cache.Definitions.Add(inkMenuInstanceSwitchToScenarioRef);

            // stuff we use in our custom function
            var stringToNameFunction = cache.GetFunction("StringToName");
            var getUISystemFunction  = cache.GetFunction("GameInstance", "GetUISystem");
            var uiSystemClass        = cache.GetClass("UISystem");
            var queueEventFunction   = uiSystemClass.GetFunction("QueueEvent");

            var myFunction = new FunctionDefinition()
            {
                Name  = "STS",
                Flags =
                    FunctionFlags.IsStatic | FunctionFlags.IsExec |
                    FunctionFlags.HasParameters | FunctionFlags.HasLocals |
                    FunctionFlags.HasCode,
                SourceFile = mySourceFile,
            };

            cache.Definitions.Add(myFunction);

            var myParameter0 = new ParameterDefinition()
            {
                Name   = "gameInstance",
                Parent = myFunction,
                Type   = gameInstanceNative,
                Flags  = ParameterFlags.None,
            };

            cache.Definitions.Add(myParameter0);
            myFunction.Parameters.Add(myParameter0);

            var myParameter1 = new ParameterDefinition()
            {
                Name   = "name",
                Parent = myFunction,
                Type   = stringNative,
                Flags  = ParameterFlags.None,
            };

            cache.Definitions.Add(myParameter1);
            myFunction.Parameters.Add(myParameter1);

            var myLocal0 = new LocalDefinition()
            {
                Name      = "event",
                Parent    = myFunction,
                Type      = inkMenuInstanceSwitchToScenarioRef,
                Unknown28 = 0,
            };

            cache.Definitions.Add(myLocal0);
            myFunction.Locals.Add(myLocal0);

            var cg = new CodeGenerator();

            // event = new inkMenuInstance_SwitchToScenario
            cg.Emit(Opcode.Assign);
            {
                cg.Emit(Opcode.LocalVar, myLocal0);
                cg.Emit(Opcode.New, inkMenuInstanceSwitchToScenarioClass);
            }

            // event.Init(StringToName(name), 0)
            var afterEventContextLabel = cg.DefineLabel();

            cg.Emit(Opcode.Context, afterEventContextLabel);
            {
                cg.Emit(Opcode.LocalVar, myLocal0);
                cg.Emit(Opcode.FinalFunc, afterEventContextLabel, 0, inkMenuInstanceSwitchToScenarioClass.Functions[0]);
                {
                    // StringToName(name)
                    var afterStringToNameLabel = cg.DefineLabel();
                    cg.Emit(Opcode.FinalFunc, afterStringToNameLabel, 0, stringToNameFunction);
                    {
                        cg.Emit(Opcode.ParamVar, myParameter1);
                        cg.Emit(Opcode.ParamEnd);
                    }
                    cg.MarkLabel(afterStringToNameLabel);
                }
                cg.Emit(Opcode.Nop);
                cg.Emit(Opcode.ParamEnd);
            }
            cg.MarkLabel(afterEventContextLabel);

            // getUISystem(gameInstance).QueueEvent(event)
            var afterUISystemContextLabel = cg.DefineLabel();

            cg.Emit(Opcode.Context, afterUISystemContextLabel);
            {
                var afterGetUISystemLabel = cg.DefineLabel();
                cg.Emit(Opcode.FinalFunc, afterGetUISystemLabel, 0, getUISystemFunction);
                {
                    cg.Emit(Opcode.ParamVar, myParameter0);
                    cg.Emit(Opcode.ParamEnd);
                }
                cg.MarkLabel(afterGetUISystemLabel);
                cg.Emit(Opcode.FinalFunc, afterUISystemContextLabel, 0, queueEventFunction);
                {
                    cg.Emit(Opcode.LocalVar, myLocal0);
                    cg.Emit(Opcode.ParamEnd);
                }
            }
            cg.MarkLabel(afterUISystemContextLabel);

            cg.Emit(Opcode.Nop);
            myFunction.Code.AddRange(cg.GetCode());
        }
Пример #50
0
 /// <summary>
 /// Create the new body of the iterator method. 
 /// </summary>
 /// <remarks>
 /// Pseudo code:
 /// iteratorClosureLocal = new Closure(0);
 /// iteratorClosureLocal.field = parameter; // for each parameter including this. 
 /// return iteratorClosureLocal;
 /// </remarks>
 private BlockStatement CreateNewIteratorMethodBody(IteratorClosureInformation iteratorClosure) {
   BlockStatement result = new BlockStatement();
   // iteratorClosureLocal = new IteratorClosure(0);
   LocalDefinition localDefinition = new LocalDefinition() {
     Name = this.host.NameTable.GetNameFor("iteratorClosureLocal"),
     Type = GetClosureTypeReferenceFromIterator(iteratorClosure),
   };
   CreateObjectInstance createObjectInstance = new CreateObjectInstance() {
     MethodToCall = GetMethodReference(iteratorClosure, iteratorClosure.Constructor),
     Type = localDefinition.Type
   };
   // the start state depends on whether the iterator is an IEnumerable or an IEnumerator. For the former,
   // it must be created in state -2. Then it is the GetEnumerator method that puts it into its
   // "start" state, i.e., state 0.
   var startState = this.isEnumerable ? -2 : 0;
   createObjectInstance.Arguments.Add(new CompileTimeConstant() { Value = startState, Type = this.host.PlatformType.SystemInt32 });
   LocalDeclarationStatement localDeclarationStatement = new LocalDeclarationStatement() {
     InitialValue = createObjectInstance,
     LocalVariable = localDefinition
   };
   result.Statements.Add(localDeclarationStatement);
   // Generate assignments to closure instance's fields for each of the parameters captured by the closure. 
   foreach (object capturedLocalOrParameter in FieldForCapturedLocalOrParameter.Keys) {
     BoundField boundField = FieldForCapturedLocalOrParameter[capturedLocalOrParameter];
     Assignment assignment;
     ITypeReference localOrParameterType = GetLocalOrParameterType(capturedLocalOrParameter);
     if (capturedLocalOrParameter is ILocalDefinition) continue;
     if (capturedLocalOrParameter is IThisReference) {
       var thisR = new ThisReference();
       IExpression thisValue = thisR;
       if (!this.method.ContainingTypeDefinition.IsClass) {
         thisValue = new AddressDereference() {
           Address = thisR,
           Type = this.method.ContainingTypeDefinition.IsGeneric ? (ITypeReference)this.method.ContainingTypeDefinition.InstanceType : (ITypeReference)this.method.ContainingTypeDefinition
         };
       }
       assignment = new Assignment {
         Source = thisValue,
         Type = this.method.ContainingType,
         Target = new TargetExpression() {
           Definition = GetFieldReference(iteratorClosure, boundField.Field),
           Type = this.method.ContainingType,
           Instance = new BoundExpression() {
             Type = localDefinition.Type,
             Instance = null,
             Definition = localDefinition,
             IsVolatile = false
           }
         },
       };
     } else {
       assignment = new Assignment {
         Source = new BoundExpression() {
           Definition = capturedLocalOrParameter,
           Instance = null,
           IsVolatile = false,
           Type = localOrParameterType
         },
         Type = localOrParameterType,
         Target = new TargetExpression() {
           Definition = GetFieldReference(iteratorClosure, boundField.Field),
           Type = localOrParameterType,
           Instance = new BoundExpression() {
             Type = localDefinition.Type,
             Instance = null,
             Definition = localDefinition,
             IsVolatile = false
           }
         },
       };
     }
     ExpressionStatement expressionStatement = new ExpressionStatement() { Expression = assignment };
     result.Statements.Add(expressionStatement);
   }
   // Generate: return iteratorClosureLocal;
   result.Statements.Add(new ReturnStatement() {
     Expression = new BoundExpression() { Definition = localDeclarationStatement.LocalVariable, Instance = null, Type = localDeclarationStatement.LocalVariable.Type }
   });
   return result;
 }
    delegate void Action(); //not defined in CLR v2.

    /// <summary>
    /// Saves the current closure fields. Allocates a new closure and updates the fields. Then calls the given delegate and
    /// restores the earlier state.
    /// </summary>
    private void AllocateClosureFor(object scope, List<IStatement> statements, Action rewriteScope) {
      Contract.Assume(!this.isInsideAnonymousMethod);
      var savedCurrentClosure = this.currentClosureClass;
      var savedCurrentClosureSelfInstance = this.currentClosureSelfInstance;
      var savedCurrentClosureInstance = this.currentClosureInstance;
      var savedCurrentClosureObject = this.currentClosureObject;
      var savedCurrentClosureLocal = this.currentClosureLocal;
      this.CreateClosureClass();
      IFieldReference outerClosure = null;
      if (savedCurrentClosureLocal != null) {
        this.CreateClosureField(this.currentClosureSelfInstance, savedCurrentClosureSelfInstance, savedCurrentClosureInstance, savedCurrentClosureLocal.Name.Value);
        outerClosure = this.fieldReferencesForUseInsideThisMethod[this.currentClosureSelfInstance];
      }

      var closureLocal = new LocalDefinition() { Type = this.currentClosureInstance, Name = this.host.NameTable.GetNameFor("CS$<>__locals"+this.closureClasses.Count) };
      this.currentClosureObject = new BoundExpression() { Definition = closureLocal, Type = this.currentClosureInstance };
      this.currentClosureLocal = closureLocal;
      if (this.closureLocalInstances == null) this.closureLocalInstances = new List<IExpression>();
      this.closureLocalInstances.Add(this.currentClosureObject);
      rewriteScope();
      Statement createClosure = new ExpressionStatement() {
        Expression = new Assignment() {
          Target = new TargetExpression() { Definition = closureLocal, Type = closureLocal.Type },
          Source = new CreateObjectInstance() {
            MethodToCall = this.GetReferenceToDefaultConstructor(this.currentClosureInstance),
            Type = currentClosureSelfInstance,
          }
        }
      };
      ILabeledStatement labeledStatement = null;
      for (int i = 0, n = statements.Count; i < n; i++) {
        labeledStatement = statements[i] as ILabeledStatement;
        if (labeledStatement != null) {
          createClosure = new LabeledStatement() { Label = labeledStatement.Label, Statement = createClosure };
          createClosure.Locations.AddRange(labeledStatement.Locations);
          statements[i] = labeledStatement.Statement;
          break;
        } else if (statements[i] is IEmptyStatement) {
          continue;
        } else {
          var declSt = statements[i] as ILocalDeclarationStatement;
          if (declSt != null && declSt.InitialValue == null) continue;
          break;
        }
      }
      statements.Insert(0, createClosure);
      if (outerClosure != null) {
        statements.Insert(1, new ExpressionStatement() {
          Expression = new Assignment() {
            Target = new TargetExpression() { Instance = new BoundExpression() { Definition = closureLocal, Type = closureLocal.Type }, Definition = outerClosure, Type = closureLocal.Type },
            Source = new BoundExpression() { Definition = savedCurrentClosureLocal, Type = savedCurrentClosureLocal.Type }, 
            Type = closureLocal.Type,
          }
        });
      }
      this.currentClosureClass = savedCurrentClosure;
      this.currentClosureSelfInstance = savedCurrentClosureSelfInstance;
      this.currentClosureInstance = savedCurrentClosureInstance;
      this.currentClosureObject = savedCurrentClosureObject;
      this.currentClosureLocal = savedCurrentClosureLocal;
    }
Пример #52
0
 /// <summary>
 /// Create a mutable copy of a local definition. 
 /// </summary>
 /// <param name="localDefinition"></param>
 /// <returns></returns>
 protected virtual LocalDefinition GetMutableCopy(ILocalDefinition localDefinition)
 {
     object cachedValue;
       if (this.cache.TryGetValue(localDefinition, out cachedValue)) {
     return (LocalDefinition)cachedValue;
       }
       var result = new LocalDefinition();
       result.Copy(localDefinition, this.host.InternFactory);
       this.cache.Add(localDefinition, result);
       this.cache.Add(result, result);
       return result;
 }
Пример #53
0
        // this function creates all methods that are needed for the generated graph
        public void createGraphMethods() {

            this.logger.writeLine("Adding graph methods to \"" + this.targetClass.ToString() + "\"");

            // check if the graph is already initialized (needed to create the methods)
            if (this.graph == null) {
                throw new ArgumentException("Graph is not initialized.");
            }

            // if debugging is activated
            // => add field for the basic block trace file
            if (this.debugging
                || this.trace) {

                this.logger.writeLine("Debugging activated: Adding field for a basic block tracer file");

                // add trace writer field
                this.debuggingTraceWriter = new FieldDefinition();
                this.debuggingTraceWriter.IsCompileTimeConstant = false;
                this.debuggingTraceWriter.IsNotSerialized = false;
                this.debuggingTraceWriter.IsReadOnly = false;
                this.debuggingTraceWriter.IsRuntimeSpecial = false;
                this.debuggingTraceWriter.IsSpecialName = false;
                this.debuggingTraceWriter.Type = this.helperClass.systemIOStreamWriter;
                this.debuggingTraceWriter.IsStatic = false;
                this.debuggingTraceWriter.Name = host.NameTable.GetNameFor("DEBUG_traceWriter");
                this.debuggingTraceWriter.Visibility = TypeMemberVisibility.Public;
                this.debuggingTraceWriter.InternFactory = host.InternFactory;
                this.debuggingTraceWriter.ContainingTypeDefinition = this.targetClass;
                this.targetClass.Fields.Add(this.debuggingTraceWriter);

            }

            // create a method that can be called to generate the graph
            this.buildGraphMethod = this.helperClass.createNewMethod("buildGraph", this.targetClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, false, true); // TODO RENAME

            ILGenerator ilGenerator = new ILGenerator(host, this.buildGraphMethod);

            // check if graph was already build
            // => if it was jump to exit
            ILGeneratorLabel buildGraphExitLabel = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerGet);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brfalse, buildGraphExitLabel);
            
            // set initial node (root of the tree)
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldarg_0); // needed as argument for the constructor
            ilGenerator.Emit(OperationCode.Newobj, this.graph.startingNode.constructorToUse);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerSet);

            // build rest of graph in a "pseudo recursive" manner
            MethodDefinition newMethodToCall = this.addNodeRecursively(this.graph.startingNode, 1, "addNode_0"); // TODO: method name
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerGet);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Callvirt, newMethodToCall);

            // exit
            ilGenerator.MarkLabel(buildGraphExitLabel);
            ilGenerator.Emit(OperationCode.Ret);

            // create body
            IMethodBody body = new ILGeneratorMethodBody(ilGenerator, true, 8, this.buildGraphMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty);
            this.buildGraphMethod.Body = body;

            // create exchangeNodes method
            List<IParameterDefinition> parameters = new List<IParameterDefinition>();
            // node type parameter
            ParameterDefinition parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = this.nodeInterface;
            parameters.Add(parameter);
            // int array parameter for path to node one
            VectorTypeReference intArrayType = new VectorTypeReference();
            intArrayType.ElementType = this.host.PlatformType.SystemInt32;
            intArrayType.Rank = 1;
            intArrayType.IsFrozen = true;
            intArrayType.IsValueType = false;
            intArrayType.InternFactory = host.InternFactory;
            parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = intArrayType;
            parameters.Add(parameter);
            // int array parameter for path to node two
            parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = intArrayType;
            parameters.Add(parameter);

            this.exchangeNodesMethod = this.helperClass.createNewMethod("exchangeNodes", this.targetClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO RENAME

            ilGenerator = new ILGenerator(host, this.exchangeNodesMethod);
            List<ILocalDefinition> localVariables = new List<ILocalDefinition>();

            // create local integer variable needed for the loops
            LocalDefinition loopIntLocal = new LocalDefinition();
            loopIntLocal.IsReference = false;
            loopIntLocal.IsPinned = false;
            loopIntLocal.IsModified = false;
            loopIntLocal.Type = this.host.PlatformType.SystemInt32;
            loopIntLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(loopIntLocal);

            // create local iNode variable needed for nodeOne
            LocalDefinition nodeOneLocal = new LocalDefinition();
            nodeOneLocal.IsReference = false;
            nodeOneLocal.IsPinned = false;
            nodeOneLocal.IsModified = false;
            nodeOneLocal.Type = this.nodeInterface;
            nodeOneLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(nodeOneLocal);

            // create local iNode variable needed for prevNodeOne
            LocalDefinition prevNodeOneLocal = new LocalDefinition();
            prevNodeOneLocal.IsReference = false;
            prevNodeOneLocal.IsPinned = false;
            prevNodeOneLocal.IsModified = false;
            prevNodeOneLocal.Type = this.nodeInterface;
            prevNodeOneLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(prevNodeOneLocal);

            // create local integer variable needed for prevNodeOneIdx
            LocalDefinition prevNodeOneIdxLocal = new LocalDefinition();
            prevNodeOneIdxLocal.IsReference = false;
            prevNodeOneIdxLocal.IsPinned = false;
            prevNodeOneIdxLocal.IsModified = false;
            prevNodeOneIdxLocal.Type = this.host.PlatformType.SystemInt32;
            prevNodeOneIdxLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(prevNodeOneIdxLocal);

            // create local iNode variable needed for nodeTwo
            LocalDefinition nodeTwoLocal = new LocalDefinition();
            nodeTwoLocal.IsReference = false;
            nodeTwoLocal.IsPinned = false;
            nodeTwoLocal.IsModified = false;
            nodeTwoLocal.Type = this.nodeInterface;
            nodeTwoLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(nodeTwoLocal);

            // create local iNode variable needed for prevNodeOne
            LocalDefinition prevNodeTwoLocal = new LocalDefinition();
            prevNodeTwoLocal.IsReference = false;
            prevNodeTwoLocal.IsPinned = false;
            prevNodeTwoLocal.IsModified = false;
            prevNodeTwoLocal.Type = this.nodeInterface;
            prevNodeTwoLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(prevNodeTwoLocal);

            // create local integer variable needed for prevNodeOneIdx
            LocalDefinition prevNodeTwoIdxLocal = new LocalDefinition();
            prevNodeTwoIdxLocal.IsReference = false;
            prevNodeTwoIdxLocal.IsPinned = false;
            prevNodeTwoIdxLocal.IsModified = false;
            prevNodeTwoIdxLocal.Type = this.host.PlatformType.SystemInt32;
            prevNodeTwoIdxLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(prevNodeTwoIdxLocal);

            // create local iNode variable needed for temp
            LocalDefinition tempNodeLocal = new LocalDefinition();
            tempNodeLocal.IsReference = false;
            tempNodeLocal.IsPinned = false;
            tempNodeLocal.IsModified = false;
            tempNodeLocal.Type = this.nodeInterface;
            tempNodeLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(tempNodeLocal);

            // initialize local variables
            /*
            iNode nodeOne = givenStartingNode;
            iNode prevNodeOne = null;
            int prevNodeOneIdx = 0;
            */
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Stloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeOneIdxLocal);

            // initialize loop
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);
            ILGeneratorLabel loopConditionAndIncBranch = new ILGeneratorLabel();
            ILGeneratorLabel loopConditionBranch = new ILGeneratorLabel();
            ILGeneratorLabel loopStartBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Br, loopConditionBranch);

            // start of the code in the loop
            /*
            if (nodeOne.getNode(pathToNodeOne[i]) != null) {
            */
            ilGenerator.MarkLabel(loopStartBranch);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldarg_2);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldelem_I4);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, loopConditionAndIncBranch);

            // get the node of the graph that should be exchanged (nodeOne)
            /*
            prevNodeOne = nodeOne;
            prevNodeOneIdx = pathToNodeOne[i];
            nodeOne = nodeOne.getNode(pathToNodeOne[i]);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldarg_2);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldelem_I4);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeOneIdxLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeOneIdxLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Stloc, nodeOneLocal);

            // increment counter of loop
            ilGenerator.MarkLabel(loopConditionAndIncBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);

            // loop condition
            /*
            for (int i = 0; i < pathToNodeOne.Length; i++) {
            */
            ilGenerator.MarkLabel(loopConditionBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldarg_2);
            ilGenerator.Emit(OperationCode.Ldlen);
            ilGenerator.Emit(OperationCode.Conv_I4);
            ilGenerator.Emit(OperationCode.Clt);
            ilGenerator.Emit(OperationCode.Brtrue, loopStartBranch);

            // initialize local variables
            /*
            iNode nodeTwo = givenStartingNode;
            iNode prevNodeTwo = null;
            int prevNodeTwoIdx = 0;
            */
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Stloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeTwoIdxLocal);

            // initialize loop
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);
            loopConditionAndIncBranch = new ILGeneratorLabel();
            loopConditionBranch = new ILGeneratorLabel();
            loopStartBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Br, loopConditionBranch);

            // start of the code in the loop
            /*
            if (nodeTwo.getNode(pathToNodeTwo[i]) != null) {
            */
            ilGenerator.MarkLabel(loopStartBranch);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldarg_3);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldelem_I4);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, loopConditionAndIncBranch);

            // get the node of the graph that should be exchanged (nodeTwo)
            /*
            prevNodeTwo = nodeTwo;
            prevNodeTwoIdx = pathToNodeTwo[i];
            nodeTwo = nodeTwo.getNode(pathToNodeTwo[i]);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldarg_2);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldelem_I4);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeTwoIdxLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeTwoIdxLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Stloc, nodeTwoLocal);

            // increment counter of loop
            ilGenerator.MarkLabel(loopConditionAndIncBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);

            // loop condition
            /*
            for (int i = 0; i < pathToNodeTwo.Length; i++) {
            */
            ilGenerator.MarkLabel(loopConditionBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldarg_3);
            ilGenerator.Emit(OperationCode.Ldlen);
            ilGenerator.Emit(OperationCode.Conv_I4);
            ilGenerator.Emit(OperationCode.Clt);
            ilGenerator.Emit(OperationCode.Brtrue, loopStartBranch);

            // initialize loop
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);
            loopConditionAndIncBranch = new ILGeneratorLabel();
            loopConditionBranch = new ILGeneratorLabel();
            loopStartBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Br, loopConditionBranch);

            // start of the code in the loop
            ilGenerator.MarkLabel(loopStartBranch);

            /*
            if (nodeOne.getNode(i) == nodeTwo) {
            */
            ILGeneratorLabel conditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brfalse, conditionBranch);

            /*
            nodeOne.setNode(nodeTwo.getNode(i), i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);

            /*
            nodeTwo.setNode(nodeOne, i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);
            ilGenerator.Emit(OperationCode.Br, loopConditionAndIncBranch);

            /*
            else if (nodeTwo.getNode(i) == nodeOne) {
            */
            ilGenerator.MarkLabel(conditionBranch);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ceq);
            conditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Brfalse, conditionBranch);

            /*
            nodeTwo.setNode(nodeOne.getNode(i), i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);

            /*
            nodeOne.setNode(nodeTwo, i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);
            ilGenerator.Emit(OperationCode.Br, loopConditionAndIncBranch);

            /*
            else {
            */
            ilGenerator.MarkLabel(conditionBranch);

            /*
            temp = nodeOne.getNode(i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Stloc, tempNodeLocal);

            /*
            nodeOne.setNode(nodeTwo.getNode(i), i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);

            /*
            nodeTwo.setNode(temp, i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, tempNodeLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);

            // increment counter of loop
            ilGenerator.MarkLabel(loopConditionAndIncBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);

            // loop condition
            /*
            for (int i = 0; i < GRAPH_DIMENSION; i++) {
            */
            ilGenerator.MarkLabel(loopConditionBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4, this.graphDimension);
            ilGenerator.Emit(OperationCode.Clt);
            ilGenerator.Emit(OperationCode.Brtrue, loopStartBranch);

            /*
            if (prevNodeOne != null) {
            */
            conditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, conditionBranch);

            /*
            if (prevNodeOne != nodeTwo) {
            */
            ILGeneratorLabel exitConditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, exitConditionBranch);

            /*
            prevNodeOne.setNode(nodeTwo, prevNodeOneIdx);
            */
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeOneIdxLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);
            ilGenerator.Emit(OperationCode.Br, exitConditionBranch);

            /*
            else {
            */
            ilGenerator.MarkLabel(conditionBranch);

            /*
            this.graphStartNode = nodeTwo;
            */
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerSet);

            ilGenerator.MarkLabel(exitConditionBranch);

            /*
            if (prevNodeTwo != null) {
            */
            conditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, conditionBranch);

            /*
            if (prevNodeTwo != nodeOne) {
            */
            exitConditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, exitConditionBranch);

            /*
            prevNodeTwo.setNode(nodeOne, prevNodeTwoIdx);
            */
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeTwoIdxLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);
            ilGenerator.Emit(OperationCode.Br, exitConditionBranch);

            /*
            else {
            */
            ilGenerator.MarkLabel(conditionBranch);

            /*
            this.graphStartNode = nodeOne;
            */
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerSet);

            ilGenerator.MarkLabel(exitConditionBranch);
            ilGenerator.Emit(OperationCode.Ret);

            // create body
            body = new ILGeneratorMethodBody(ilGenerator, true, 8, this.exchangeNodesMethod, localVariables, Enumerable<ITypeDefinition>.Empty);
            this.exchangeNodesMethod.Body = body;

            // check if debugging is activated
            // => add function to dump graph as .dot file
            if (this.debugging) {

                this.logger.writeLine("Debugging activated: Adding code to dump graph as .dot file");

                // create dumpGraph method
                parameters = new List<IParameterDefinition>();
                // string parameter
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.host.PlatformType.SystemString;
                parameter.Index = 0;
                parameters.Add(parameter);
                // node type parameter (current pointer of debug method)
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.nodeInterface;
                parameter.Index = 1;
                parameters.Add(parameter);
                // node type parameter (current pointer of caller)
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.nodeInterface;
                parameter.Index = 2;
                parameters.Add(parameter);

                this.debuggingDumpGraphMethod = this.helperClass.createNewMethod("DEBUG_dumpGraph", this.targetClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true);

                // create dumpGraphRec method
                parameters = new List<IParameterDefinition>();
                // stream writer parameter
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.helperClass.systemIOStreamWriter;
                parameter.Index = 0;
                parameters.Add(parameter);
                // string parameter
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.host.PlatformType.SystemString;
                parameter.Index = 1;
                parameters.Add(parameter);
                // node type parameter (current pointer of debug method)
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.nodeInterface;
                parameter.Index = 2;
                parameters.Add(parameter);
                // node type parameter (current pointer of caller)
                ParameterDefinition currentNodeCallerParameter = new ParameterDefinition();
                currentNodeCallerParameter.IsIn = false;
                currentNodeCallerParameter.IsOptional = false;
                currentNodeCallerParameter.IsOut = false;
                currentNodeCallerParameter.Type = this.nodeInterface;
                currentNodeCallerParameter.Index = 3;
                parameters.Add(currentNodeCallerParameter);

                MethodDefinition dumpGraphRecMethod = this.helperClass.createNewMethod("DEBUG_dumpGraphRec", this.targetClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true);
                currentNodeCallerParameter.ContainingSignature = dumpGraphRecMethod; // is needed when parameter is accessed via Ldarg

                // create body for dumpGraph method
                ilGenerator = new ILGenerator(host, this.debuggingDumpGraphMethod);
                localVariables = new List<ILocalDefinition>();

                // create local string variable needed for debugging code
                LocalDefinition nodeNameLocal = new LocalDefinition();
                nodeNameLocal.IsReference = false;
                nodeNameLocal.IsPinned = false;
                nodeNameLocal.IsModified = false;
                nodeNameLocal.Type = this.host.PlatformType.SystemString;
                nodeNameLocal.MethodDefinition = this.debuggingDumpGraphMethod;
                localVariables.Add(nodeNameLocal);

                // create local stream writer variable needed for debugging code
                LocalDefinition streamWriterLocal = new LocalDefinition();
                streamWriterLocal.IsReference = false;
                streamWriterLocal.IsPinned = false;
                streamWriterLocal.IsModified = false;
                streamWriterLocal.Type = this.helperClass.systemIOStreamWriter;
                streamWriterLocal.MethodDefinition = this.debuggingDumpGraphMethod;
                localVariables.Add(streamWriterLocal);

                // create local integer variable for the for loop needed for debugging code
                LocalDefinition forIntegerLocal = new LocalDefinition();
                forIntegerLocal.IsReference = false;
                forIntegerLocal.IsPinned = false;
                forIntegerLocal.IsModified = false;
                forIntegerLocal.Type = this.host.PlatformType.SystemInt32;
                forIntegerLocal.MethodDefinition = this.debuggingDumpGraphMethod;
                localVariables.Add(forIntegerLocal);

                // generate dump file location string
                ilGenerator.Emit(OperationCode.Ldstr, this.debuggingDumpLocation + this.debuggingDumpFilePrefix);
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldstr, ".dot");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // initialize io stream writer
                ilGenerator.Emit(OperationCode.Newobj, this.helperClass.streamWriterCtor);
                ilGenerator.Emit(OperationCode.Stloc, streamWriterLocal);

                // initialize .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "digraph G {");
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // check if the node to dump is the same as the current node of the class
                // if it is => color the current dumped node
                ilGenerator.Emit(OperationCode.Ldarg_3);
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ceq);
                ILGeneratorLabel currentNodeEqualDumpedNodeBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Brtrue, currentNodeEqualDumpedNodeBranch);

                // case: current dumped node is not the current node of the class
                // create name for the nodes
                ilGenerator.Emit(OperationCode.Ldstr, "node_0");
                ilGenerator.Emit(OperationCode.Stloc, nodeNameLocal);

                // write current node to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, " [shape=record]");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // jump to the end of this case
                ILGeneratorLabel currentNodeDumpedBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Br, currentNodeDumpedBranch);

                // case: current dumped node is the current node of the class
                ilGenerator.MarkLabel(currentNodeEqualDumpedNodeBranch);

                // create name for the nodes
                ilGenerator.Emit(OperationCode.Ldstr, "node_0");
                ilGenerator.Emit(OperationCode.Stloc, nodeNameLocal);

                // write current node to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, " [shape=record, color=blue]");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // end of the case
                ilGenerator.MarkLabel(currentNodeDumpedBranch);

                // write start of label of the current node to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, " [label=\"{");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write current node name to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "Node: ");
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "|");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write current node id to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "Id: ");
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Callvirt, this.debuggingInterfaceIdGet);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write end of label of the current node to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "}\"]");
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // initialize counter of for loop
                ilGenerator.Emit(OperationCode.Ldc_I4_0);
                ilGenerator.Emit(OperationCode.Stloc, forIntegerLocal);

                // jump to loop condition
                loopConditionBranch = new ILGeneratorLabel();
                loopStartBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Br, loopConditionBranch);

                // start of loop
                ilGenerator.MarkLabel(loopStartBranch);

                // check if childNodes[i] == startNode
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
                ilGenerator.Emit(OperationCode.Ldarg_0);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerGet);
                ilGenerator.Emit(OperationCode.Ceq);
                loopConditionAndIncBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Brtrue, loopConditionAndIncBranch);

                // write connection of current node to next node to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);

                // generate first part of the string
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, " -> ");
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // generate second part of string and concat to first part
                ilGenerator.Emit(OperationCode.Ldstr, "_");
                ilGenerator.Emit(OperationCode.Ldloca, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.int32ToString);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // write to .dot file
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // call method that dumps graph recursively ( this.dumpGraphRec(streamWriter, String name, nextNode) )
                ilGenerator.Emit(OperationCode.Ldarg_0);

                // push stream writer parameter
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);

                // push string parameter
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "_");
                ilGenerator.Emit(OperationCode.Ldloca, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.int32ToString);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // push node parameter (current pointer of debug method)
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);

                // push node parameter (current pointer of the caller)
                ilGenerator.Emit(OperationCode.Ldarg_3);

                ilGenerator.Emit(OperationCode.Callvirt, dumpGraphRecMethod);

                // increment loop counter
                ilGenerator.MarkLabel(loopConditionAndIncBranch);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Ldc_I4_1);
                ilGenerator.Emit(OperationCode.Add);
                ilGenerator.Emit(OperationCode.Stloc, forIntegerLocal);

                // loop condition
                ilGenerator.MarkLabel(loopConditionBranch);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Ldc_I4, this.graphDimension);
                ilGenerator.Emit(OperationCode.Clt);
                ilGenerator.Emit(OperationCode.Brtrue, loopStartBranch);

                // end .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "}");
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // close io stream writer                
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterClose);

                ilGenerator.Emit(OperationCode.Ret);

                // create body
                body = new ILGeneratorMethodBody(ilGenerator, true, 8, this.debuggingDumpGraphMethod, localVariables, Enumerable<ITypeDefinition>.Empty);
                this.debuggingDumpGraphMethod.Body = body;

                // create body for dumpGraphRec method
                localVariables = new List<ILocalDefinition>();
                ilGenerator = new ILGenerator(host, dumpGraphRecMethod);

                // create local integer variable for the for loop needed for debugging code
                forIntegerLocal = new LocalDefinition();
                forIntegerLocal.IsReference = false;
                forIntegerLocal.IsPinned = false;
                forIntegerLocal.IsModified = false;
                forIntegerLocal.Type = this.host.PlatformType.SystemInt32;
                forIntegerLocal.MethodDefinition = dumpGraphRecMethod;
                localVariables.Add(forIntegerLocal);

                // check if the node to dump is the same as the current node of the class
                // if it is => color the current dumped node
                ilGenerator.Emit(OperationCode.Ldarg, currentNodeCallerParameter);
                ilGenerator.Emit(OperationCode.Ldarg_3);
                ilGenerator.Emit(OperationCode.Ceq);
                currentNodeEqualDumpedNodeBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Brtrue, currentNodeEqualDumpedNodeBranch);

                // case: current dumped node is not the current node of the class
                // write current node to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, " [shape=record]");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // jump to the end of this case
                currentNodeDumpedBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Br, currentNodeDumpedBranch);

                // case: current dumped node is the current node of the class
                ilGenerator.MarkLabel(currentNodeEqualDumpedNodeBranch);

                // write current node to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, " [shape=record, color=blue]");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // end of the case
                ilGenerator.MarkLabel(currentNodeDumpedBranch);

                // write start of label of the current node to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, " [label=\"{");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write current node name to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldstr, "Node: ");
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, "|");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write current node id to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldstr, "Id: ");
                ilGenerator.Emit(OperationCode.Ldarg_3);
                ilGenerator.Emit(OperationCode.Callvirt, this.debuggingInterfaceIdGet);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write end of label of the current node to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldstr, "}\"]");
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // initialize counter of for loop
                ilGenerator.Emit(OperationCode.Ldc_I4_0);
                ilGenerator.Emit(OperationCode.Stloc, forIntegerLocal);

                // jump to loop condition
                loopConditionBranch = new ILGeneratorLabel();
                loopStartBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Br, loopConditionBranch);

                // start of loop
                ilGenerator.MarkLabel(loopStartBranch);

                // check if childNodes[i] == startNode
                ilGenerator.Emit(OperationCode.Ldarg_3);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
                ilGenerator.Emit(OperationCode.Ldarg_0);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerGet);
                ilGenerator.Emit(OperationCode.Ceq);
                loopConditionAndIncBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Brtrue, loopConditionAndIncBranch);

                // write connection of current node to next node to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);

                // generate first part of the string
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, " -> ");
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // generate second part of string and concat to first part
                ilGenerator.Emit(OperationCode.Ldstr, "_");
                ilGenerator.Emit(OperationCode.Ldloca, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.int32ToString);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // write to .dot file
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // call method that dumps graph recursively ( this.dumpGraphRec(streamWriter, String name, nextNode) )
                ilGenerator.Emit(OperationCode.Ldarg_0);

                // push stream writer parameter
                ilGenerator.Emit(OperationCode.Ldarg_1);

                // push string parameter
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, "_");
                ilGenerator.Emit(OperationCode.Ldloca, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.int32ToString);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // push node parameter (current pointer of debug method)
                ilGenerator.Emit(OperationCode.Ldarg_3);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);

                // push node parameter (current pointer of the caller)
                ilGenerator.Emit(OperationCode.Ldarg, currentNodeCallerParameter);

                ilGenerator.Emit(OperationCode.Callvirt, dumpGraphRecMethod);

                // increment loop counter
                ilGenerator.MarkLabel(loopConditionAndIncBranch);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Ldc_I4_1);
                ilGenerator.Emit(OperationCode.Add);
                ilGenerator.Emit(OperationCode.Stloc, forIntegerLocal);

                // loop condition
                ilGenerator.MarkLabel(loopConditionBranch);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Ldc_I4, this.graphDimension);
                ilGenerator.Emit(OperationCode.Clt);
                ilGenerator.Emit(OperationCode.Brtrue, loopStartBranch);

                ilGenerator.Emit(OperationCode.Ret);

                // create body
                body = new ILGeneratorMethodBody(ilGenerator, true, 8, dumpGraphRecMethod, localVariables, Enumerable<ITypeDefinition>.Empty);
                dumpGraphRecMethod.Body = body;

            }

            // inject code to build the graph to all constructors (except the artificial added ctor for a graph node)
            foreach (MethodDefinition ctorMethod in this.targetClass.Methods) {

                // only process constructors
                if (!ctorMethod.IsConstructor) {
                    continue;
                }

                // skip the artificial added ctor with the node interface as parameter
                bool skip = false;
                if (ctorMethod.Parameters != null) {
                    foreach (IParameterDefinition ctorParameter in ctorMethod.Parameters) {
                        if (ctorParameter.Type == this.nodeInterface) {
                            skip = true;
                            break;
                        }
                    }
                }
                if (skip) {
                    continue;
                }

                this.logger.writeLine("Injecting code to build graph to \"" + this.logger.makeFuncSigString(ctorMethod) + "\"");

                MethodCfg ctorMethodCfg = this.cfgBuilder.buildCfgForMethod(ctorMethod);

                // create new basic block that builds the graph
                // (will be the new starting basic block of the method)
                BasicBlock startBasicBlock = new BasicBlock();
                startBasicBlock.startIdx = 0;
                startBasicBlock.endIdx = 0;

                startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.buildGraphMethod));

                if (this.debugging) {

                    // dump generated graph
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, this.debuggingNumber.ToString().PadLeft(3, '0') + "_obfu_" + this.logger.makeFuncSigString(ctorMethodCfg.method)));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.debuggingDumpGraphMethod));

                }

                // create exit branch for the new start basic block
                NoBranchTarget startExitBranch = new NoBranchTarget();
                startExitBranch.sourceBasicBlock = startBasicBlock;
                startBasicBlock.exitBranch = startExitBranch;

                // set the original start basic block as the target of the exit branch
                startExitBranch.takenTarget = ctorMethodCfg.startBasicBlock;
                ctorMethodCfg.startBasicBlock.entryBranches.Add(startExitBranch);

                // set new start basic block as start basic block of the method cfg
                ctorMethodCfg.startBasicBlock = startBasicBlock;
                ctorMethodCfg.basicBlocks.Add(startBasicBlock);

                this.cfgBuilder.createMethodFromCfg(ctorMethodCfg);

            }

        }
Пример #54
0
 /// <summary>
 /// Deep copy a local definition. 
 /// </summary>
 /// <param name="localDefinition"></param>
 /// <returns></returns>
 protected override LocalDefinition DeepCopy(LocalDefinition localDefinition)
 {
     localDefinition.Type = this.Substitute(localDefinition.Type);
       localDefinition.CustomModifiers = this.DeepCopy(localDefinition.CustomModifiers);
       return localDefinition;
 }
Пример #55
0
        private void removeReplaceUnconditionalBranchesIter(CfgManipulator cfgManipulator, GraphRandomStateGenerator randomStateGenerator, MethodCfg originalMethodCfg, MethodCfg methodCfg, BasicBlock startBasicBlock, LocalDefinition intStateLocal, LocalDefinition currentNodeLocal) {

            // create a list of basic blocks that still have to be processed by the algorithm
            List<BasicBlock> basicBlocksToProcess = new List<BasicBlock>(methodCfg.basicBlocks);

            System.Console.WriteLine("Basic Blocks to process (Replace Unconditional Branches): " + basicBlocksToProcess.Count());

            while (true) {

                List<BasicBlock> copiedList = new List<BasicBlock>(basicBlocksToProcess);
                foreach (BasicBlock currentBasicBlock in copiedList) {

                    // check if basic block has entry branches that can be optimized
                    bool hasUnconditionalBranchTarget = false;
                    bool hasNoBranchTarget = false;
                    foreach (IBranchTarget entryBranch in currentBasicBlock.entryBranches) {
                        if ((entryBranch as NoBranchTarget) != null) {
                            hasNoBranchTarget = true;
                            continue;
                        }
                        else if ((entryBranch as UnconditionalBranchTarget) != null) {
                            hasUnconditionalBranchTarget = true;
                            continue;
                        }
                    }

                    // skip if basic block already has no branch target
                    if (hasNoBranchTarget) {
                        // remove currently processed basic block from the list of basic blocks to process
                        basicBlocksToProcess.Remove(currentBasicBlock);
                        continue;
                    }

                    // skip if basic block does not have an unconditional branch target
                    if (!hasUnconditionalBranchTarget) {
                        // remove currently processed basic block from the list of basic blocks to process
                        basicBlocksToProcess.Remove(currentBasicBlock);
                        continue;
                    }

                    // replace one unconditional branch by a no branch
                    List<IBranchTarget> copiedBranchList = new List<IBranchTarget>(currentBasicBlock.entryBranches);
                    foreach (IBranchTarget entryBranch in copiedBranchList) {

                        if ((entryBranch as UnconditionalBranchTarget) != null) {
                            BasicBlock sourceBasicBlock = entryBranch.sourceBasicBlock;

                            // create replacement branch
                            NoBranchTarget replacementBranch = new NoBranchTarget();
                            replacementBranch.sourceBasicBlock = sourceBasicBlock;
                            replacementBranch.takenTarget = currentBasicBlock;

                            // replace old branch with new one
                            sourceBasicBlock.exitBranch = replacementBranch;
                            currentBasicBlock.entryBranches.Remove(entryBranch);
                            currentBasicBlock.entryBranches.Add(replacementBranch);

                            // replace unconditional branch instruction with nop
                            IOperation lastOperation = sourceBasicBlock.operations.ElementAt(sourceBasicBlock.operations.Count() - 1);
                            if (!CfgBuilder.isUnconditionalBranchOperation(lastOperation)) {
                                throw new ArgumentException("Last instruction of basic block have to be an unconditional branch.");
                            }
                            IOperation replacementOperation = this.helperClass.createNewOperation(OperationCode.Nop);
                            sourceBasicBlock.operations[sourceBasicBlock.operations.Count() - 1] = replacementOperation;

                            break;
                        }

                    }

                    // remove currently processed basic block from the list of basic blocks to process
                    basicBlocksToProcess.Remove(currentBasicBlock);

                }

                System.Console.WriteLine("Basic Blocks to process (Replace Unconditional Branches): " + basicBlocksToProcess.Count());

                // check if basic blocks exist to process => if not break loop
                if (basicBlocksToProcess.Count() == 0) {
                    break;
                }

            }

        }
Пример #56
0
 public LocalPlace(LocalDefinition def)
 {
     Contract.ThrowIfNull(def);
     _def = def;
 }
 public override void RewriteChildren(LocalDefinition localDefinition)
 {
     //The locals have already been copied. They just have to get fixed up.
     localDefinition.MethodDefinition = this.method;
 }
      public override IExpression Rewrite(IBoundExpression boundExpression) {

        if (boundExpression.Instance == null || ExpressionTraverser.IsAtomicInstance(boundExpression.Instance)) return boundExpression;

        // boundExpression == BE(inst, def), i.e., inst.def
        // return { loc := e; [assert loc != null;] | BE(BE(null,loc), def) }, i.e., "loc := e; loc.def"
        //   where e is the rewritten inst

        var e = base.Rewrite(boundExpression.Instance);

        var loc = new LocalDefinition() {
          Name = this.host.NameTable.GetNameFor("_loc" + this.sink.LocalCounter.ToString()),
          Type = e.Type,
        };
        var locDecl = new LocalDeclarationStatement() {
          InitialValue = e,
          LocalVariable = loc,
        };
        return new BlockExpression() {
          BlockStatement = new BlockStatement() {
            Statements = new List<IStatement> { locDecl },
          },
          Expression = new BoundExpression() {
            Definition = boundExpression.Definition,
            Instance = new BoundExpression() {
              Definition = loc,
              Instance = null,
              Type = loc.Type,
            },
            Type = boundExpression.Type,
          },
        };

      }
      public override IExpression Rewrite(IArrayIndexer arrayIndexer) {
        if (ExpressionTraverser.IsAtomicInstance(arrayIndexer.IndexedObject)) return arrayIndexer;

        // arrayIndexer == AI(inst, [index]), i.e., inst[index0, index1,...]
        // return { loc := e; [assert loc != null;] | AI(BE(null,loc), [index]) }
        //   where e is the rewritten array instance

        var e = base.Rewrite(arrayIndexer.IndexedObject);

        var loc = new LocalDefinition() {
          Name = this.host.NameTable.GetNameFor("_loc" + this.sink.LocalCounter.ToString()),
          Type = e.Type
        };
        var locDecl = new LocalDeclarationStatement() {
          InitialValue = e,
          LocalVariable = loc,
        };
        return new BlockExpression() {
          BlockStatement = new BlockStatement() {
            Statements = new List<IStatement> { locDecl },
          },
          Expression = new ArrayIndexer() {
            IndexedObject = new BoundExpression() {
              Definition = loc,
              Instance = null,
              Type = loc.Type,
            },
            Indices = new List<IExpression>(arrayIndexer.Indices),
            Type = arrayIndexer.Type,
          },
        };
      }
Пример #60
0
    public override void RewriteChildren(MethodBody methodBody) {
      var method = methodBody.MethodDefinition;
      Contract.Assume(this.copier.OriginalFor.ContainsKey(method));
      var o = this.copier.OriginalFor[method];
      var originalMethod = (IMethodDefinition)o;
      var keepEntireBody = this.methodDefsToKeep.Contains(originalMethod.InternedKey);
      if (!keepEntireBody) {
        #region Keep only contract portion of the IL (if it has a contract), add return statement at end
        var ops = new List<IOperation>();

        uint contractOffset;
        if (this.contractOffsets.TryGetValue(originalMethod, out contractOffset)) {
          if (contractOffset != uint.MaxValue) { // then it has a contract
            foreach (var op in methodBody.Operations) {
              if (contractOffset < op.Offset) break;
              ops.Add(op);
            }
          }
        }

        LocalDefinition ld = null;
        if (method.Type.TypeCode != PrimitiveTypeCode.Void) {
          ld = new LocalDefinition() {
            MethodDefinition = method,
            Type = method.Type,
          };
          ops.Add(new Operation() { OperationCode = OperationCode.Ldloc, Value = ld, });
          methodBody.LocalsAreZeroed = true;
        }
        ops.Add(new Operation() { OperationCode = OperationCode.Ret, });
        if (ld != null) {
          if (methodBody.LocalVariables == null)
            methodBody.LocalVariables = new List<ILocalDefinition>();
          methodBody.LocalVariables.Add(ld);
          methodBody.MaxStack++;
        }
        #endregion
        methodBody.Operations = ops;
        methodBody.OperationExceptionInformation = null;
      }
    }