public void InitializeTest() { const int loops = 10; Tensor x_tensor = new Tensor(Shape.Scalar(), new float[] { 0.7f }); Tensor y_tensor = new Tensor(Shape.Scalar(), new float[] { 0.8f }); ParameterField x = x_tensor, y = y_tensor; Field f = Square(x) + Square(y); Field g = Square(Sin(x + Sin(y))) + Square(Sin(y + Sin(x))); Field loss = f / 20 + g; StoreField lossnode = loss.Save(); (Flow flow, Parameters parameters) = Flow.Optimize(loss); parameters.AddUpdater((parameter) => new SGD(parameter, lambda: 0.01f)); Snapshot snapshot = parameters.Save(); List <float> losses_first = new List <float>(), xs_first = new List <float>(), ys_first = new List <float>(); for (int i = 0; i < loops; i++) { flow.Execute(); parameters.Update(); losses_first.Add(lossnode.State[0]); xs_first.Add(x_tensor.State[0]); ys_first.Add(y_tensor.State[0]); } x_tensor.State = new float[] { 0.7f }; y_tensor.State = new float[] { 0.8f }; parameters.InitializeUpdater(); List <float> losses_second = new List <float>(), xs_second = new List <float>(), ys_second = new List <float>(); for (int i = 0; i < loops; i++) { flow.Execute(); parameters.Update(); losses_second.Add(lossnode.State[0]); xs_second.Add(x_tensor.State[0]); ys_second.Add(y_tensor.State[0]); } CollectionAssert.AreEqual(losses_first, losses_second); CollectionAssert.AreEqual(xs_first, xs_second); CollectionAssert.AreEqual(ys_first, ys_second); parameters.Load(snapshot); List <float> losses_third = new List <float>(), xs_third = new List <float>(), ys_third = new List <float>(); for (int i = 0; i < loops; i++) { flow.Execute(); parameters.Update(); losses_third.Add(lossnode.State[0]); xs_third.Add(x_tensor.State[0]); ys_third.Add(y_tensor.State[0]); } CollectionAssert.AreEqual(losses_first, losses_third); CollectionAssert.AreEqual(xs_first, xs_third); CollectionAssert.AreEqual(ys_first, ys_third); }
static void Train(Iterator train_iterator, MnistLoader loader, VariableField x, VariableField t, StoreField accnode, StoreField lossnode, Flow trainflow, Parameters parameters) { Stopwatch sw = new Stopwatch(); sw.Start(); while (train_iterator.Epoch < 50) { (float[] images, float[] labels) = loader.GetTrain(train_iterator.Next()); x.ValueTensor.State = images; t.ValueTensor.State = labels; trainflow.Execute(enable_processing_time: true); parameters.Update(); if (train_iterator.Iteration % 100 != 0) { continue; } float train_acc = accnode.State[0]; float train_loss = lossnode.State[0]; Console.WriteLine($"[{train_iterator.Iteration}] train acc: {train_acc:F3} train loss: {train_loss:E3}"); } sw.Stop(); Console.WriteLine($"{sw.ElapsedMilliseconds} msec, {sw.ElapsedMilliseconds / train_iterator.Epoch} msec/epoch"); }
public void VisitStoreField(StoreField field) { DoAdd(field.Field.FieldType); }
static void Test(Iterator test_iterator, MnistLoader loader, VariableField x, VariableField t, Flow testflow, StoreField accnode) { List <float> test_acc_list = new List <float>(); Stopwatch sw = new Stopwatch(); sw.Start(); while (test_iterator.Epoch < 1) { (float[] images, float[] labels) = loader.GetTest(test_iterator.Next()); x.ValueTensor.State = images; t.ValueTensor.State = labels; testflow.Execute(); float test_acc = accnode.State[0]; test_acc_list.Add(test_acc); } sw.Stop(); Console.WriteLine($"{sw.ElapsedMilliseconds} msec"); Console.WriteLine($"[Result] acc: {test_acc_list.Average():F5}"); }
static void Main() { const string dirpath_dataset = "mnist_dataset"; const string dirpath_result = "result"; const int classes = 10; Console.WriteLine("Download mnist..."); MnistDownloader.Download(dirpath_dataset); Console.WriteLine("Setup loader..."); Random random = new Random(1234); MnistLoader loader = new MnistLoader(dirpath_dataset, num_batches: 1000); Iterator train_iterator = new ShuffleIterator(loader.NumBatches, loader.CountTrainDatas, random); Iterator test_iterator = new ShuffleIterator(loader.NumBatches, loader.CountTestDatas, random); Console.WriteLine("Create input tensor..."); VariableField x = new Tensor(loader.BatchShape); VariableField t = new Tensor(Shape.Vector(loader.NumBatches)); Console.WriteLine("Build model..."); Field y = CNN.Forward(x, classes); Field acc = Accuracy(y, t); Field err = Sum(SoftmaxCrossEntropy(y, OneHotVector(t, classes)), axes: new int[] { Axis.Map0D.Channels }); StoreField accnode = acc.Save(), lossnode = Average(err).Save(); Console.WriteLine("Build optimize flow..."); (Flow trainflow, Parameters parameters) = Flow.Optimize(err); Console.WriteLine("Initialize params..."); parameters .Where((parameter) => parameter.Category == ParameterCategory.Kernel) .InitializeTensor((tensor) => new HeNormal(tensor, random)); parameters .Where((parameter) => parameter.Category == ParameterCategory.Bias) .InitializeTensor((tensor) => new Zero(tensor)); Console.WriteLine("Set params updater..."); parameters.AddUpdater((parameter) => new Nadam(parameter, alpha: 0.01f)); parameters.AddUpdater((parameter) => new Ridge(parameter, decay: 1e-4f)); Console.WriteLine("Training..."); Train(train_iterator, loader, x, t, accnode, lossnode, trainflow, parameters); Console.WriteLine("Build inference flow..."); Flow testflow = Flow.Inference(accnode); Console.WriteLine("Testing..."); Test(test_iterator, loader, x, t, testflow, accnode); Console.WriteLine("Saving snapshot..."); Snapshot snapshot = parameters.Save(); SnapshotSaver saver = new ZippedBinaryShapshotSaver(); if (!Directory.Exists(dirpath_result)) { Directory.CreateDirectory(dirpath_result); } saver.Save($"{dirpath_result}/mnist.tss", snapshot); Console.WriteLine("END"); Console.Read(); }
protected internal virtual void VisitStoreField(StoreField node, object data) { throw new NodeNotSupportedException(node); }
public void ReferenceTest() { const int elems = 4, classes = 2 + 1, boxes = 25, batches = 2; float[] locval = new float[elems * boxes * batches]; float[] gtval = new float[elems * boxes * batches]; float[] confval = new float[classes * boxes * batches]; float[] labelval = new float[boxes * batches] { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; for (int i = 0; i < boxes * batches; i++) { float p = ((i % 7 + 2) * 0.123f) % 1, q = ((i % 8 + 3) * 0.213f) % 1, r = ((i % 16 + 1) * 0.231f) % 1, s = ((i % 32 + 4) * 0.523f) % 1; if (labelval[i] != 0) { gtval[i * 4] = p; gtval[i * 4 + 1] = q; gtval[i * 4 + 2] = r; gtval[i * 4 + 3] = s; } locval[i * 4] = s; locval[i * 4 + 1] = p; locval[i * 4 + 2] = q; locval[i * 4 + 3] = r; confval[i * 3] = p / (p + r + s); confval[i * 3 + 1] = r / (p + r + s); confval[i * 3 + 2] = s / (p + r + s); } ParameterField loc = new Tensor(Shape.Map1D(elems, boxes, batches), locval); ParameterField conf = new Tensor(Shape.Map1D(classes, boxes, batches), confval); ParameterField gt = new Tensor(Shape.Map1D(elems, boxes, batches), gtval); ParameterField label = new Tensor(Shape.Map0D(boxes, batches), labelval); (Field locloss, Field confloss) = MultiBoxLoss(loc, gt, conf, label, hard_negative_mining_rate: 2); StoreField locloss_node = locloss.Save(); StoreField confloss_node = confloss.Save(); (Flow flow, Parameters Parameters) = Flow.Optimize(locloss, confloss); flow.Execute(); Assert.IsTrue(loc.Grad != null); Assert.IsTrue(conf.Grad != null); Assert.IsTrue(gt.Grad == null); Assert.IsTrue(label.Grad == null); float[] locloss_actual = locloss_node.Tensor.State; AssertError.Tolerance(locloss_expect, locloss_actual, 1e-6f, 1e-4f, $"not equal locloss"); float[] confloss_actual = confloss_node.Tensor.State; AssertError.Tolerance(confloss_expect, confloss_actual, 1e-6f, 1e-4f, $"not equal confloss"); float[] gloc_actual = loc.GradTensor.State; AssertError.Tolerance(gloc_expect, gloc_actual, 1e-6f, 1e-4f, $"not equal gloc"); float[] gconf_actual = conf.GradTensor.State; AssertError.Tolerance(gconf_expect, gconf_actual, 1e-6f, 1e-4f, $"not equal gconf"); }
public void WriteStoreField(StoreField s, ExpressionUsage u) { WriteStoreField(s.Source, s.Field, s.Object, s.Value, u); }
// ---------------------------------------------------------------------------------------- /// <!-- ToString --> /// <summary> /// /// </summary> /// <returns></returns> public override string ToString() { return(StoreField.ToString() + " " + Column + "(" + InTable + ")" + " " + Length + " " + Param); }
public static MethodBodyBlock Convert(MethodEx method) { if (!method.IsVerified) { throw new ConvertionException(); } MethodInfoExtention _method_ = new MethodInfoExtention(method.Method); MethodBodyBlock mainBlock = new MethodBodyBlock(_method_.GetReturnType().type); mainBlock.Options["StackTypes"] = new StackTypes(); Block currentBlock = mainBlock; Node[] heads = new Node[method.Count]; Node[] tails = new Node[method.Count]; Node head = null; Node tail = null; Node firstBlock = null; Node lastBlock = null; int iNum, iNumNext; Variable[] locals = new Variable[method.Locals.Count]; Variable[] args = new Variable[_method_.ArgCount]; VariablesList methodVarList = mainBlock.Variables; for (int i = 0; i < args.Length; i++) { args[i] = methodVarList.CreateVar(_method_.GetArgType(i).type, VariableKind.Parameter); args[i].Name = "Arg" + i; // methodVarList.Add(args[i]); } for (int i = 0; i < locals.Length; i++) { locals[i] = methodVarList.CreateVar(method.Locals[i], VariableKind.Local); locals[i].Name = "Loc" + i; // methodVarList.Add(locals[i]); } BlockType nextBlockType; int nextBlockStart = -1; int nextBlockEnd = 1 << 30; int nextBlockIndex; Type nextCatchBlockType; Hashtable tryBlocks = new Hashtable(); Hashtable filterBlocks = new Hashtable(); Stack blockEnds = new Stack(); blockEnds.Push(method.Count); FindNextBlockStart(method.EHClauses, out nextBlockType, ref nextBlockStart, ref nextBlockEnd, out nextCatchBlockType, out nextBlockIndex); //Nodes and blocks creation, blocks linkage for (iNum = 0; iNum < method.Count; iNum++) { while (iNum == (int)blockEnds.Peek()) { currentBlock = currentBlock.Parent; blockEnds.Pop(); } firstBlock = null; lastBlock = null; Node thisBlock = null; while (iNum == nextBlockStart) { Block currentBlockOld = currentBlock; switch (nextBlockType) { case BlockType.Try: currentBlock = new ProtectedBlock(); break; case BlockType.Catch: currentBlock = new CatchBlock(nextCatchBlockType); break; case BlockType.Finally: currentBlock = new FinallyBlock(false); break; case BlockType.Filter: currentBlock = new FilterBlock(); break; case BlockType.FilteredCatch: currentBlock = new UserFilteredBlock(); break; } currentBlock.setParent(currentBlockOld); blockEnds.Push(nextBlockEnd); if (thisBlock == null) { thisBlock = firstBlock = currentBlock; } else { thisBlock.Next = currentBlock; thisBlock = currentBlock; } switch (nextBlockType) { case BlockType.Try: tryBlocks.Add(new Segment(nextBlockStart, nextBlockEnd), thisBlock); break; case BlockType.Filter: filterBlocks.Add(new Segment(nextBlockStart, nextBlockEnd), thisBlock); break; case BlockType.Finally: case BlockType.Catch: { Segment tryBlockKey = FindProtectedBlock(method.EHClauses, nextBlockIndex); ProtectedBlock tryBlock = tryBlocks[tryBlockKey] as ProtectedBlock; tryBlock.AddHandler(thisBlock as EHBlock); } break; case BlockType.FilteredCatch: { Segment tryBlockKey = FindProtectedBlock(method.EHClauses, nextBlockIndex); ProtectedBlock tryBlock = tryBlocks[tryBlockKey] as ProtectedBlock; tryBlock.AddHandler(thisBlock as EHBlock); Segment filterKey = FindFilterBlock(method.EHClauses, nextBlockIndex); FilterBlock filterBlock = filterBlocks[filterKey] as FilterBlock; (thisBlock as UserFilteredBlock).Filter = filterBlock; } break; } FindNextBlockStart(method.EHClauses, out nextBlockType, ref nextBlockStart, ref nextBlockEnd, out nextCatchBlockType, out nextBlockIndex); } lastBlock = thisBlock; Instruction i = method[iNum]; switch (i.Code) { case InstructionCode.NEG: case InstructionCode.NOT: { head = tail = new UnaryOp(UnaryOpFromCode(i.Code)); /*!*/ head.setParent(currentBlock); } break; case InstructionCode.ADD: case InstructionCode.AND: case InstructionCode.CEQ: case InstructionCode.CGT: case InstructionCode.CLT: case InstructionCode.DIV: case InstructionCode.MUL: case InstructionCode.OR: case InstructionCode.REM: case InstructionCode.SHL: case InstructionCode.SHR: case InstructionCode.SUB: case InstructionCode.XOR: { head = tail = new BinaryOp(BinaryOpFromCode(i.Code), i.OverflowFlag, i.UnsignedFlag); /*!*/ head.setParent(currentBlock); } break; case InstructionCode.LDC: head = tail = new LoadConst(i.Param); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDARG: head = tail = new LoadVar(args[(int)(i.Param)]); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDLOC: head = tail = new LoadVar(locals[(int)(i.Param)]); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDARGA: head = tail = new LoadVarAddr(args[(int)(i.Param)]); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDLOCA: head = tail = new LoadVarAddr(locals[(int)(i.Param)]); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDIND: head = tail = new LoadIndirect(i.TypeBySuffixOrParam()); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDFLD: { FieldInfo field = i.Param as FieldInfo; if (field.IsStatic) { head = new RemoveStackTop(); /*!*/ head.setParent(currentBlock); //remove the object instance when accessing the static field with LDFLD tail = new LoadField(field); /*!*/ tail.setParent(currentBlock); head.Next = tail; } else { head = tail = new LoadField(field); /*!*/ head.setParent(currentBlock); } } break; case InstructionCode.LDFLDA: { FieldInfo field = i.Param as FieldInfo; if (field.IsStatic) { head = new RemoveStackTop(); /*!*/ head.setParent(currentBlock); tail = new LoadFieldAddr(field); /*!*/ tail.setParent(currentBlock); head.Next = tail; } else { head = tail = new LoadFieldAddr(field); /*!*/ head.setParent(currentBlock); } } break; case InstructionCode.LDSFLD: head = tail = new LoadField(i.Param as FieldInfo); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDSFLDA: head = tail = new LoadFieldAddr(i.Param as FieldInfo); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDELEM: head = tail = new LoadElement(i.TypeBySuffixOrParam()); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDELEMA: head = tail = new LoadElementAddr(i.TypeBySuffixOrParam()); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDOBJ: head = tail = new LoadIndirect(i.Param as Type); /*!*/ head.setParent(currentBlock); break; case InstructionCode.SIZEOF: head = tail = new LoadSizeOfValue(i.Param as Type); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDLEN: head = tail = new LoadLength(); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDTOKEN: if (i.Param is Type) { head = tail = new LoadConst((i.Param as Type).TypeHandle); } else if (i.Param is MethodBase) { head = tail = new LoadConst((i.Param as MethodBase).MethodHandle); } else if (i.Param is FieldInfo) { head = tail = new LoadConst((i.Param as FieldInfo).FieldHandle); } else { throw new ConvertionException(); } /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDNULL: head = tail = new LoadConst(null); /*!*/ head.setParent(currentBlock); break; case InstructionCode.LDSTR: head = tail = new LoadConst(i.Param); /*!*/ head.setParent(currentBlock); break; case InstructionCode.STARG: head = tail = new StoreVar(args[(int)(i.Param)]); /*!*/ head.setParent(currentBlock); break; case InstructionCode.STLOC: head = tail = new StoreVar(locals[(int)(i.Param)]); /*!*/ head.setParent(currentBlock); break; case InstructionCode.STIND: head = tail = new StoreIndirect(i.TypeBySuffixOrParam()); /*!*/ head.setParent(currentBlock); break; case InstructionCode.STFLD: { FieldInfo field = i.Param as FieldInfo; if (field.IsStatic) { head = new StoreField(field); /*!*/ head.setParent(currentBlock); tail = new RemoveStackTop(); /*!*/ tail.setParent(currentBlock); head.Next = tail; } else { head = tail = new StoreField(i.Param as FieldInfo); /*!*/ head.setParent(currentBlock); } } break; case InstructionCode.STSFLD: head = tail = new StoreField(i.Param as FieldInfo); /*!*/ head.setParent(currentBlock); break; case InstructionCode.STELEM: head = tail = new StoreElement(i.TypeBySuffixOrParam()); /*!*/ head.setParent(currentBlock); break; case InstructionCode.STOBJ: head = tail = new StoreIndirect(i.Param as Type); /*!*/ head.setParent(currentBlock); break; case InstructionCode.CPOBJ: head = new LoadIndirect(i.Param as Type); /*!*/ head.setParent(currentBlock); tail = new StoreIndirect(i.Param as Type); /*!*/ tail.setParent(currentBlock); head.Next = tail; break; case InstructionCode.DUP: head = tail = new DuplicateStackTop(); /*!*/ head.setParent(currentBlock); break; case InstructionCode.CALL: head = tail = new CallMethod(i.Param as MethodBase, false, i.HasTail); /*!*/ head.setParent(currentBlock); break; case InstructionCode.CALLVIRT: MethodInfo callee = i.Param as MethodInfo; head = tail = new CallMethod(callee, callee.IsVirtual, i.HasTail); /*!*/ head.setParent(currentBlock); break; case InstructionCode.NEWOBJ: { ConstructorInfo ctor = i.Param as ConstructorInfo; if (Verifier.IsDelegate(ctor.DeclaringType)) { if (Verifier.IsInstanceDispatch(method, iNum)) { heads[iNum - 1] = tails[iNum - 1] = null; head = tail = new CreateDelegate(ctor, method[iNum - 1].Param as MethodInfo, false); } else if (Verifier.IsVirtualDispatch(method, iNum)) { heads[iNum - 2] = tails[iNum - 2] = null; heads[iNum - 1] = tails[iNum - 1] = null; head = tail = new CreateDelegate(ctor, method[iNum - 1].Param as MethodInfo, true); } } else { head = tail = new NewObject(ctor); } /*!*/ head.setParent(currentBlock); } break; case InstructionCode.NEWARR: head = tail = new NewArray(i.Param as Type); /*!*/ head.setParent(currentBlock); break; case InstructionCode.INITOBJ: head = tail = new InitValue(i.Param as Type); /*!*/ head.setParent(currentBlock); break; case InstructionCode.ISINST: head = tail = new CastClass(i.Param as Type, false); /*!*/ head.setParent(currentBlock); break; case InstructionCode.CASTCLASS: head = tail = new CastClass(i.Param as Type, true); /*!*/ head.setParent(currentBlock); break; case InstructionCode.BOX: head = tail = new BoxValue(i.Param as Type); /*!*/ head.setParent(currentBlock); break; case InstructionCode.UNBOX: head = tail = new UnboxValue(i.Param as Type); /*!*/ head.setParent(currentBlock); break; case InstructionCode.CONV: head = tail = new ConvertValue(i.TypeBySuffixOrParam(), i.OverflowFlag, i.UnsignedFlag); /*!*/ head.setParent(currentBlock); break; case InstructionCode.POP: head = tail = new RemoveStackTop(); /*!*/ head.setParent(currentBlock); break; case InstructionCode.BEQ: head = new BinaryOp(BinaryOp.ArithOp.CEQ, false, false); /*!*/ head.setParent(currentBlock); tail = new Branch(); /*!*/ tail.setParent(currentBlock); head.Next = tail; break; case InstructionCode.BNE: head = new BinaryOp(BinaryOp.ArithOp.CEQ, false, false); /*!*/ head.setParent(currentBlock); tail = new Branch(); /*!*/ tail.setParent(currentBlock); head.Next = tail; break; case InstructionCode.BGE: if (TypeFixer.IsFloatOrCompatible(i.Stack.Top())) { head = new BinaryOp(BinaryOp.ArithOp.CLT, false, !i.UnsignedFlag); } else { head = new BinaryOp(BinaryOp.ArithOp.CLT, false, i.UnsignedFlag); } tail = new Branch(); /*!*/ head.setParent(currentBlock); /*!*/ tail.setParent(currentBlock); head.Next = tail; break; case InstructionCode.BGT: head = new BinaryOp(BinaryOp.ArithOp.CGT, false, i.UnsignedFlag); tail = new Branch(); /*!*/ head.setParent(currentBlock); /*!*/ tail.setParent(currentBlock); head.Next = tail; break; case InstructionCode.BLE: if (TypeFixer.IsFloatOrCompatible(i.Stack.Top())) { head = new BinaryOp(BinaryOp.ArithOp.CGT, false, !i.UnsignedFlag); } else { head = new BinaryOp(BinaryOp.ArithOp.CGT, false, i.UnsignedFlag); } tail = new Branch(); /*!*/ head.setParent(currentBlock); /*!*/ tail.setParent(currentBlock); head.Next = tail; break; case InstructionCode.BLT: head = new BinaryOp(BinaryOp.ArithOp.CLT, false, i.UnsignedFlag); tail = new Branch(); /*!*/ head.setParent(currentBlock); /*!*/ tail.setParent(currentBlock); head.Next = tail; break; case InstructionCode.BRTRUE: head = tail = new Branch(); /*!*/ head.setParent(currentBlock); break; case InstructionCode.BRFALSE: head = tail = new Branch(); /*!*/ head.setParent(currentBlock); break; case InstructionCode.SWITCH: head = tail = new Switch((i.Param as int[]).Length); /*!*/ head.setParent(currentBlock); break; case InstructionCode.BR: case InstructionCode.NOP: case InstructionCode.BREAK: case InstructionCode.LDFTN: // Expecting further delegate construction... case InstructionCode.LDVIRTFTN: // head = tail = new DummyNode(); /*!*/ head.setParent(currentBlock); break; case InstructionCode.THROW: head = tail = new ThrowException(); /*!*/ head.setParent(currentBlock); break; case InstructionCode.RET: case InstructionCode.ENDFINALLY: case InstructionCode.ENDFILTER: case InstructionCode.LEAVE: head = tail = new Leave(); /*!*/ head.setParent(currentBlock); break; default: throw new ConvertionException(); } if (head != null) { head.Options["StackTypes"] = i.Stack.Clone() as StackTypes; } if (head != tail) //=> head :: BinaryOp, tail :: Branch //|| head :: LoadIndirect, tail :: StoreIndirect { if (head is BinaryOp && tail is Branch) { StackTypes stack = i.Stack.Clone() as StackTypes; stack.Pop(); stack.Pop(); stack.Push(typeof(int)); tail.Options["StackTypes"] = stack; } else if (head is LoadIndirect && tail is StoreIndirect) { StackTypes stack = i.Stack.Clone() as StackTypes; TypeEx type = stack.Pop(); //type == S& stack.Push(type.type.GetElementType()); tail.Options["StackTypes"] = stack; } } if (firstBlock != null) { lastBlock.Next = head; for (Node n = firstBlock; n != head; n = n.Next) { n.Options["StackTypes"] = i.Stack.Clone() as StackTypes; } head = firstBlock; if (tail == null) { tail = lastBlock; //This may occure what the NOP instruction starts some block } } heads[iNum] = head; tails[iNum] = tail; } //for mainBlock.Next = heads[0]; //Control flow linkage for (iNum = 0; iNum < method.Count; iNum++) { if (heads[iNum] == null) { throw new ConvertionException(); //impossible :) } Instruction i = method[iNum]; switch (i.Code) { case InstructionCode.BR: case InstructionCode.LEAVE: tails[iNum].Next = heads[(int)i.Param]; break; case InstructionCode.RET: case InstructionCode.ENDFINALLY: case InstructionCode.ENDFILTER: case InstructionCode.THROW: case InstructionCode.RETHROW: break; case InstructionCode.BRFALSE: //false case InstructionCode.BGE: //false case InstructionCode.BLE: //false case InstructionCode.BNE: //false tails[iNum].Next = heads[(int)i.Param]; (tails[iNum] as Branch).Alt = heads[iNum + 1]; break; case InstructionCode.BRTRUE: //true case InstructionCode.BEQ: //true case InstructionCode.BGT: //true case InstructionCode.BLT: //true tails[iNum].Next = heads[iNum + 1]; (tails[iNum] as Branch).Alt = heads[(int)i.Param]; break; case InstructionCode.SWITCH: tails[iNum].Next = heads[iNum + 1]; Switch node = tails[iNum] as Switch; int[] alt = i.Param as int[]; for (int j = 0; j < node.Count; j++) { node[j] = heads[alt[j]]; } break; default: tails[iNum].Next = heads[iNum + 1]; break; } } //Removing DummyNodes for (iNum = 0; iNum < method.Count; iNum++) { if (heads[iNum] is DummyNode) { Node dummy = heads[iNum]; Node[] prev = new Node[dummy.PrevArray.Count]; for (int j = 0; j < prev.Length; j++) { prev[j] = dummy.PrevArray[j]; } for (int j = 0; j < prev.Length; j++) { prev[j].NextArray[prev[j].NextArray.IndexOf(dummy)] = dummy.Next; } dummy.RemoveFromGraph(); } } return(mainBlock); }