private static IMethodDefinition CreateStringArrayMarshallingEpilog(IMetadataHost host, ITypeDefinition typeDef, IFieldReference intPtrZero, IMethodReference intPtrOpInequality, IMethodReference freeHGlobal) { var intPtrArrayType = new VectorTypeReference { ElementType = host.PlatformType.SystemIntPtr, Rank = 1 }; MethodDefinition methodDefinition = new MethodDefinition { ContainingTypeDefinition = typeDef, IsStatic = true, Visibility = TypeMemberVisibility.Assembly, Type = host.PlatformType.SystemVoid, Parameters = new List <IParameterDefinition> { new ParameterDefinition { Index = 0, Type = intPtrArrayType } }, Name = host.NameTable.GetNameFor("StringArrayMarshallingEpilog") }; var size = new LocalDefinition { Type = host.PlatformType.SystemInt32 }; var index = new LocalDefinition { Type = host.PlatformType.SystemInt32 }; var locals = new List <ILocalDefinition> { size, index }; var ilGenerator = new ILGenerator(host, methodDefinition); var loopStart = new ILGeneratorLabel(); var loopBackEdge = new ILGeneratorLabel(); var exitLabel = new ILGeneratorLabel(); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldlen); ilGenerator.Emit(OperationCode.Conv_I4); ilGenerator.Emit(OperationCode.Stloc_0); ilGenerator.Emit(OperationCode.Ldc_I4_0); ilGenerator.Emit(OperationCode.Stloc_1); ilGenerator.Emit(OperationCode.Br_S, loopBackEdge); ilGenerator.MarkLabel(loopStart); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Ldelem_I); ilGenerator.Emit(OperationCode.Ldsfld, intPtrZero); ilGenerator.Emit(OperationCode.Call, intPtrOpInequality); ilGenerator.Emit(OperationCode.Brfalse_S, exitLabel); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Ldelem_I); ilGenerator.Emit(OperationCode.Call, freeHGlobal); ilGenerator.MarkLabel(exitLabel); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Ldc_I4_1); ilGenerator.Emit(OperationCode.Add); ilGenerator.Emit(OperationCode.Stloc_1); ilGenerator.MarkLabel(loopBackEdge); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Blt_S, loopStart); ilGenerator.Emit(OperationCode.Ret); methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 2, methodDefinition, locals, new List <ITypeDefinition>()); return(methodDefinition); }
private static IMethodDefinition CreateStringArrayMarshallingProlog(IMetadataHost host, ITypeDefinition typeDef, IMethodReference stringToHGlobal, string methodName) { var stringArrayType = new VectorTypeReference { ElementType = host.PlatformType.SystemString, Rank = 1 }; var intPtrArrayType = new VectorTypeReference { ElementType = host.PlatformType.SystemIntPtr, Rank = 1 }; MethodDefinition methodDefinition = new MethodDefinition { ContainingTypeDefinition = typeDef, IsStatic = true, Visibility = TypeMemberVisibility.Assembly, Parameters = new List <IParameterDefinition> { new ParameterDefinition { Index = 0, Type = stringArrayType }, new ParameterDefinition { Index = 1, Type = intPtrArrayType } }, Type = host.PlatformType.SystemVoid, Name = host.NameTable.GetNameFor(methodName) }; var size = new LocalDefinition { Type = host.PlatformType.SystemInt32 }; var index = new LocalDefinition { Type = host.PlatformType.SystemInt32 }; var locals = new List <ILocalDefinition> { size, index }; var ilGenerator = new ILGenerator(host, methodDefinition); var loopStart = new ILGeneratorLabel(); var loopBackEdge = new ILGeneratorLabel(); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldlen); ilGenerator.Emit(OperationCode.Conv_I4); ilGenerator.Emit(OperationCode.Stloc_0); ilGenerator.Emit(OperationCode.Ldc_I4_0); ilGenerator.Emit(OperationCode.Stloc_1); ilGenerator.Emit(OperationCode.Br_S, loopBackEdge); ilGenerator.MarkLabel(loopStart); ilGenerator.Emit(OperationCode.Ldarg_1); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Ldelem_Ref); ilGenerator.Emit(OperationCode.Call, stringToHGlobal); ilGenerator.Emit(OperationCode.Stelem_I); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Ldc_I4_1); ilGenerator.Emit(OperationCode.Add); ilGenerator.Emit(OperationCode.Stloc_1); ilGenerator.MarkLabel(loopBackEdge); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Blt_S, loopStart); ilGenerator.Emit(OperationCode.Ret); methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 4, methodDefinition, locals, new List <ITypeDefinition>()); return(methodDefinition); }
// 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); } }
private static IMethodDefinition CreateStringToAnsi(IMetadataHost host, ITypeDefinition typeDef, IMethodReference getLength, IMethodReference getChars) { var byteType = host.PlatformType.SystemUInt8; var byteArrayType = new VectorTypeReference { ElementType = byteType, Rank = 1 }; MethodDefinition methodDefinition = new MethodDefinition { ContainingTypeDefinition = typeDef, IsStatic = true, Visibility = TypeMemberVisibility.Assembly, Type = byteArrayType.ResolvedArrayType, Parameters = new List <IParameterDefinition> { new ParameterDefinition { Type = host.PlatformType.SystemString } }, Name = host.NameTable.GetNameFor("StringToAnsiByteArray") }; var length = new LocalDefinition { Type = host.PlatformType.SystemInt32 }; var byteArray = new LocalDefinition { Type = byteArrayType.ResolvedArrayType }; var loopIndex = new LocalDefinition { Type = host.PlatformType.SystemInt32 }; var locals = new List <ILocalDefinition> { length, byteArray, loopIndex }; var ilGenerator = new ILGenerator(host, methodDefinition); var nullCaseLabel = new ILGeneratorLabel(); var loopStart = new ILGeneratorLabel(); var loopBackEdge = new ILGeneratorLabel(); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Brtrue_S, nullCaseLabel); ilGenerator.Emit(OperationCode.Ldnull); ilGenerator.Emit(OperationCode.Ret); ilGenerator.MarkLabel(nullCaseLabel); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Call, getLength); ilGenerator.Emit(OperationCode.Stloc_0); ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Ldc_I4_1); ilGenerator.Emit(OperationCode.Add); ilGenerator.Emit(OperationCode.Newarr, byteArrayType); ilGenerator.Emit(OperationCode.Stloc_1); ilGenerator.Emit(OperationCode.Ldc_I4_0); ilGenerator.Emit(OperationCode.Stloc_2); ilGenerator.Emit(OperationCode.Br_S, loopStart); ilGenerator.MarkLabel(loopBackEdge); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Ldloc_2); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldloc_2); ilGenerator.Emit(OperationCode.Call, getChars); ilGenerator.Emit(OperationCode.Conv_U1); ilGenerator.Emit(OperationCode.Stelem_I1); ilGenerator.Emit(OperationCode.Ldloc_2); ilGenerator.Emit(OperationCode.Ldc_I4_1); ilGenerator.Emit(OperationCode.Add); ilGenerator.Emit(OperationCode.Stloc_2); ilGenerator.MarkLabel(loopStart); ilGenerator.Emit(OperationCode.Ldloc_2); ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Blt_S, loopBackEdge); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Ldc_I4_0); ilGenerator.Emit(OperationCode.Stelem_I1); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Ret); methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 8, methodDefinition, locals, new List <ITypeDefinition>()); return(methodDefinition); }
// this function adds the created iNode interface to the class and also implements all neded functions public void addNodeInterfaceToTargetClass(NamespaceTypeDefinition givenClass) { this.logger.writeLine(""); this.logger.writeLine("Add node interface \"" + this.nodeInterface.ToString() + "\" to class \"" + givenClass.ToString() + "\""); // check if generated interface was already added to target class if (givenClass.Interfaces != null && givenClass.Interfaces.Contains(this.nodeInterface)) { this.logger.writeLine("Class \"" + givenClass.ToString() + "\" already contains node interface \"" + this.nodeInterface.ToString() + "\""); return; } // add nodes interface to class if (givenClass.Interfaces != null) { givenClass.Interfaces.Add(this.nodeInterface); } else { givenClass.Interfaces = new List<ITypeReference>(); givenClass.Interfaces.Add(this.nodeInterface); } // add start pointer field FieldDefinition startPointerField = new FieldDefinition(); startPointerField.IsCompileTimeConstant = false; startPointerField.IsNotSerialized = false; startPointerField.IsReadOnly = false; startPointerField.IsRuntimeSpecial = false; startPointerField.IsSpecialName = false; startPointerField.Type = this.nodeInterface; startPointerField.IsStatic = false; startPointerField.Visibility = TypeMemberVisibility.Public; startPointerField.Name = host.NameTable.GetNameFor("startPointer"); startPointerField.InternFactory = host.InternFactory; startPointerField.ContainingTypeDefinition = givenClass; if (givenClass.Fields != null) { givenClass.Fields.Add(startPointerField); } else { givenClass.Fields = new List<IFieldDefinition>(); givenClass.Fields.Add(startPointerField); } // create getter for the startPointer variable MethodDefinition startPointerGetMethod = this.helperClass.createNewMethod("startPointer_get", givenClass, this.nodeInterface, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the getter method ILGenerator ilGenerator = new ILGenerator(host, startPointerGetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldfld, startPointerField); ilGenerator.Emit(OperationCode.Ret); IMethodBody body = new ILGeneratorMethodBody(ilGenerator, true, 1, startPointerGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); startPointerGetMethod.Body = body; // create setter for the startPointer variable List<IParameterDefinition> parameters = new List<IParameterDefinition>(); ParameterDefinition parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Name = host.NameTable.GetNameFor("value"); parameter.Type = this.nodeInterface; parameters.Add(parameter); MethodDefinition startPointerSetMethod = this.helperClass.createNewMethod("startPointer_set", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the setter method ilGenerator = new ILGenerator(host, startPointerSetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldarg_1); ilGenerator.Emit(OperationCode.Stfld, startPointerField); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, startPointerSetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); startPointerSetMethod.Body = body; // add childNodes array field FieldDefinition childNodesField = new FieldDefinition(); childNodesField.IsCompileTimeConstant = false; childNodesField.IsNotSerialized = false; childNodesField.IsReadOnly = false; childNodesField.IsRuntimeSpecial = false; childNodesField.IsSpecialName = false; // create array of node interface type VectorTypeReference nodeInterfaceArrayType = new VectorTypeReference(); nodeInterfaceArrayType.ElementType = this.nodeInterface; nodeInterfaceArrayType.Rank = 1; nodeInterfaceArrayType.IsFrozen = true; nodeInterfaceArrayType.IsValueType = false; nodeInterfaceArrayType.InternFactory = host.InternFactory; childNodesField.Type = nodeInterfaceArrayType; childNodesField.IsStatic = false; childNodesField.Visibility = TypeMemberVisibility.Public; childNodesField.Name = host.NameTable.GetNameFor("childNodes"); childNodesField.InternFactory = host.InternFactory; childNodesField.ContainingTypeDefinition = givenClass; givenClass.Fields.Add(childNodesField); // create getter for the childNodes variable parameters = new List<IParameterDefinition>(); // int parameter parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Type = this.host.PlatformType.SystemInt32; parameters.Add(parameter); MethodDefinition childNodesGetMethod = this.helperClass.createNewMethod("childNodes_get", givenClass, this.nodeInterface, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the getter method ilGenerator = new ILGenerator(host, childNodesGetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldfld, childNodesField); ilGenerator.Emit(OperationCode.Ldarg_1); ilGenerator.Emit(OperationCode.Ldelem_Ref); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, childNodesGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); childNodesGetMethod.Body = body; // create setter for the childNodes variable parameters = new List<IParameterDefinition>(); // iNode parameter parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Type = this.nodeInterface; parameters.Add(parameter); // int parameter parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Type = this.host.PlatformType.SystemInt32; parameters.Add(parameter); MethodDefinition childNodesSetMethod = this.helperClass.createNewMethod("childNodes_set", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the setter method ilGenerator = new ILGenerator(host, childNodesSetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldfld, childNodesField); ilGenerator.Emit(OperationCode.Ldarg_2); ilGenerator.Emit(OperationCode.Ldarg_1); ilGenerator.Emit(OperationCode.Stelem_Ref); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, childNodesSetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); childNodesSetMethod.Body = body; // add current node field FieldDefinition currentNodeField = new FieldDefinition(); currentNodeField.IsCompileTimeConstant = false; currentNodeField.IsNotSerialized = false; currentNodeField.IsReadOnly = false; currentNodeField.IsRuntimeSpecial = false; currentNodeField.IsSpecialName = false; currentNodeField.Type = this.nodeInterface; currentNodeField.IsStatic = false; currentNodeField.Visibility = TypeMemberVisibility.Public; currentNodeField.Name = host.NameTable.GetNameFor("currentNode"); currentNodeField.InternFactory = host.InternFactory; currentNodeField.ContainingTypeDefinition = givenClass; givenClass.Fields.Add(currentNodeField); // create getter for the currentNode variable MethodDefinition currentNodeGetMethod = this.helperClass.createNewMethod("currentNode_get", givenClass, this.nodeInterface, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the getter method ilGenerator = new ILGenerator(host, currentNodeGetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldfld, currentNodeField); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, currentNodeGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); currentNodeGetMethod.Body = body; // create setter for the currentNode variable parameters = new List<IParameterDefinition>(); parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Name = host.NameTable.GetNameFor("value"); parameter.Type = this.nodeInterface; parameters.Add(parameter); MethodDefinition currentNodeSetMethod = this.helperClass.createNewMethod("currentNode_set", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the setter method ilGenerator = new ILGenerator(host, currentNodeSetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldarg_1); ilGenerator.Emit(OperationCode.Stfld, currentNodeField); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, currentNodeSetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); currentNodeSetMethod.Body = body; // check if debugging is activated // => add graph debugging attributes and methods MethodDefinition objectIdGetMethod = null; FieldDefinition objectIdField = null; if (this.debugging) { this.logger.writeLine("Debugging activated: Adding field for unique object id and getter method"); // add objectId field objectIdField = new FieldDefinition(); objectIdField.IsCompileTimeConstant = false; objectIdField.IsNotSerialized = false; objectIdField.IsReadOnly = false; objectIdField.IsRuntimeSpecial = false; objectIdField.IsSpecialName = false; objectIdField.Type = this.host.PlatformType.SystemString; objectIdField.IsStatic = false; objectIdField.Name = host.NameTable.GetNameFor("DEBUG_objectId"); objectIdField.Visibility = TypeMemberVisibility.Public; objectIdField.InternFactory = host.InternFactory; objectIdField.ContainingTypeDefinition = givenClass; givenClass.Fields.Add(objectIdField); // create getter for the objectId variable objectIdGetMethod = this.helperClass.createNewMethod("DEBUG_objectId_get", givenClass, this.host.PlatformType.SystemString, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the getter method ilGenerator = new ILGenerator(host, objectIdGetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldfld, objectIdField); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, objectIdGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); objectIdGetMethod.Body = body; } // add .ctor(iNode) to target class parameters = new List<IParameterDefinition>(); parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Type = this.nodeInterface; parameters.Add(parameter); MethodDefinition nodeConstructor = this.helperClass.createNewMethod(".ctor", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, false); nodeConstructor.IsSpecialName = true; nodeConstructor.IsHiddenBySignature = true; nodeConstructor.IsRuntimeSpecial = true; // generate node constructor body ilGenerator = new ILGenerator(host, currentNodeSetMethod); // create local variable list List<ILocalDefinition> localVariables = new List<ILocalDefinition>(); // call system.object constructor ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Call, this.helperClass.objectCtor); // initialize childNodes array ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldc_I4, this.graphDimension); ilGenerator.Emit(OperationCode.Newarr, nodeInterfaceArrayType); ilGenerator.Emit(OperationCode.Stfld, childNodesField); // check if debugging is activated // => add code to constructor that generates a unique id for this object if (this.debugging) { this.logger.writeLine("Debugging activated: Adding code to generate unique id to node constructor"); // create local integer variable needed for debugging code LocalDefinition intLocal = new LocalDefinition(); intLocal.IsReference = false; intLocal.IsPinned = false; intLocal.IsModified = false; intLocal.Type = this.host.PlatformType.SystemInt32; intLocal.MethodDefinition = nodeConstructor; localVariables.Add(intLocal); // use the hash code of this instance as unique object id ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.objectGetHashCode); ilGenerator.Emit(OperationCode.Stloc, intLocal); // cast random integer to string and store in object id ilGenerator.Emit(OperationCode.Ldloca, intLocal); ilGenerator.Emit(OperationCode.Call, this.helperClass.int32ToString); ilGenerator.Emit(OperationCode.Stfld, objectIdField); } ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 8, nodeConstructor, localVariables, Enumerable<ITypeDefinition>.Empty); nodeConstructor.Body = body; // add class to the list of possible nodes for the graph PossibleNode tempStruct = new PossibleNode(); tempStruct.nodeConstructor = nodeConstructor; tempStruct.givenClass = givenClass; // for each interface the class implements add it to the according list foreach (ITypeReference interfaceRef in givenClass.Interfaces) { this.logger.writeLine("Add class \"" + givenClass.ToString() + "\" to graph interface list \"" + interfaceRef.ToString() + "\""); // check if a list with this interface already exists // => if it does just add current class to list if (this.graphInterfaces.ContainsKey(interfaceRef)) { List<PossibleNode> tempList = (List<PossibleNode>)this.graphInterfaces[interfaceRef]; tempList.Add(tempStruct); } // if not => add new list for this interface else { List<PossibleNode> tempList = new List<PossibleNode>(); tempList.Add(tempStruct); this.graphInterfaces.Add(interfaceRef, tempList); } } this.logger.writeLine(""); }