public void AddToUsage(VarUsage usage) { if (!isEmpty) { for (int i = 0; i < UsageArray.Count - 1; i++) { if (UsageArray[i] is StoreVar) { StoreVar storer = UsageArray[i] as StoreVar; if (UsageArray[i + 1] is LoadVar) { usage.addUsage(storer, UsageArray[i + 1] as LoadVar); } } } if (UsageArray.Count > 0 && UsageArray[UsageArray.Count - 1] is StoreVar) { StoreVar storer = UsageArray[UsageArray.Count - 1] as StoreVar; bool flag = true; for (int i = 0; i < next.Count && flag; i++) { BasicBlockStub nextStub = next[i] as BasicBlockStub; if (nextStub.UsageArray[0] is LoadVar) { usage.addUsage(storer, nextStub.UsageArray[0] as LoadVar); flag = false; } } } } }
protected internal override void VisitStoreVar(StoreVar node, object data) { StackTypes stack = data as StackTypes; Verifier.ProcessSt(new TypeEx(node.Var.Type), stack); AddTask(node.Next, stack); }
private bool performVariableAliasesRemoval() { bool result = false; foreach (Variable v in mbb.Variables) { if (v.UsersArray.Count == 1) { Node varUseNode = v.UsersArray[0]; if (varUseNode is LoadVar) { BasicBlock block = varUseNode.Options[BasicBlock.BASIC_BLOCK_OPTION] as BasicBlock; Node nextNode = varUseNode.Next; while (nextNode is DuplicateStackTop && nextNode.Options[BasicBlock.BASIC_BLOCK_OPTION] == block) { nextNode = nextNode.Next; } if (nextNode is StoreVar && nextNode.Options[BasicBlock.BASIC_BLOCK_OPTION] == block) { LoadVar ldNode = varUseNode as LoadVar; StoreVar stNode = nextNode as StoreVar; Variable var = ldNode.Var, alias = stNode.Var; if (var != alias && var.Type.Equals(alias.Type)) { result = true; replaceNodeByPop(stNode); stNode.RemoveFromGraph(); NodeArray aliasUsageList = new NodeArray(); foreach (Node node in alias.UsersArray) { aliasUsageList.Add(node); } foreach (ManageVar node in aliasUsageList) { node.Var = var; } } } } } } return(result); }
protected override void VisitStoreVar(StoreVar node, object data) { state.Perform_StoreVar(node.Var); nextNode = node.Next; }
private bool performUnnecessaryStoringRemoval() { bool result = false; bool containsProtectedBlock = false; MethodBodyBlock mbb = Entry.Body[0] as MethodBodyBlock; foreach (Node node in mbb.ChildArray) { containsProtectedBlock |= node is ProtectedBlock; } if (containsProtectedBlock) { Hashtable varFlags = new Hashtable(); foreach (BasicBlock block in blockList) { int i; NodeArray body = block.Body; if (body.Count > 0) { Node lastNode = body[body.Count - 1]; bool initialFlag = lastNode is Leave && lastNode.Parent is MethodBodyBlock; foreach (Variable var in mbb.Variables) { varFlags[var] = initialFlag; } for (i = body.Count - 1; i >= 0; i--) { Node node = body[i]; if (node is LoadVar || node is StoreVar) { Variable var = (node as ManageVar).Var; if (varIsNotReferenced(var)) { bool flag = (bool)(varFlags[var]); if (node is LoadVar && flag) { varFlags[var] = false; } else if (node is StoreVar && !flag) { varFlags[var] = true; } else if (node is StoreVar && flag) { result = true; replaceNodeByPop(node); node.RemoveFromGraph(); } } } } } } } else { foreach (Variable var in mbb.Variables) { if (varIsNotReferenced(var)) { VarUsage usage = analyseVariable(var); NodeArray nodesToRemove = new NodeArray(); foreach (ManageVar node in var.UsersArray) { if (node is StoreVar) { StoreVar storer = node as StoreVar; if (!usage.IsUsed(storer)) { nodesToRemove.Add(storer); } } } foreach (StoreVar storer in nodesToRemove) { result = true; replaceNodeByPop(storer); storer.RemoveFromGraph(); } } } } return(result); }
private bool performPatternReplacing() { bool result = false; foreach (BasicBlock block in blockList) { NodeArray body = block.Body; bool flag = true; while (flag) { flag = false; for (int i = 0; i < body.Count - 1 && !flag; i++) { Node n1 = body[i]; if (n1 is Branch && (n1 as Branch).Next == (n1 as Branch).Alt) { result = flag = true; Node n = newRemoveStackTop(block); body[i] = n; n1.ReplaceByNode(n); n.Next = n1.Next; n1.RemoveFromGraph(); } else { Node n2 = body[i + 1]; if (n1 is StoreVar && n2 is LoadVar && (n1 as ManageVar).Var == (n2 as ManageVar).Var) { result = flag = true; Node n = newDuplicateStackTop(block); body[i] = n; body[i + 1] = n1; n1.ReplaceByNode(n); n.Next = n1; n1.Next = n2.Next; n2.RemoveFromGraph(); } else if (detectedDoubleLoading(n1, n2)) { result = flag = true; Node n = newDuplicateStackTop(block); body[i + 1] = n; n2.ReplaceByNode(n); n.Next = n2.Next; n2.RemoveFromGraph(); } else if (detectedDoubleCasting(n1, n2)) { result = flag = true; body.RemoveAt(i + 1); n1.Next = n2.Next; n2.RemoveFromGraph(); } else if (n1 is StoreVar && n2 is Leave && n2.Parent is MethodBodyBlock) { result = flag = true; Node n = newRemoveStackTop(block); body[i] = n; n1.ReplaceByNode(n); n1.RemoveFromGraph(); n.Next = n2; } else if (detectedReplacementByPop(n1, n2)) { result = flag = true; Node n = newRemoveStackTop(block); body.RemoveAt(i + 1); body[i] = n; n1.ReplaceByNode(n); n1.RemoveFromGraph(); n.Next = n2.Next; n2.RemoveFromGraph(); } else if (detectedReplacementByDoublePop(n1, n2)) { result = flag = true; Node new1 = newRemoveStackTop(block), new2 = newRemoveStackTop(block); body[i] = new1; body[i + 1] = new2; n1.ReplaceByNode(new1); n1.RemoveFromGraph(); new1.Next = new2; new2.Next = n2.Next; n2.RemoveFromGraph(); } else if (detectedRemoval(n1, n2)) { result = flag = true; body.RemoveAt(i + 1); body.RemoveAt(i); n1.ReplaceByNode(n2.Next); n1.RemoveFromGraph(); n2.RemoveFromGraph(); } else if (detectedInitValueReplacement(n1, n2)) { result = flag = true; Variable var = (n1 as LoadVarAddr).Var; Type type = (n2 as InitValue).Type; object constant = null; if (type == typeof(Int64)) { constant = (Int64)0; } else if (type == typeof(Single) || type == typeof(Double)) { constant = (Double)0; } else { constant = (Int32)0; } Node new1 = new LoadConst(constant), new2 = new StoreVar(var); new1.Options[BasicBlock.BASIC_BLOCK_OPTION] = block; new2.Options[BasicBlock.BASIC_BLOCK_OPTION] = block; body[i] = new1; body[i + 1] = new2; n1.ReplaceByNode(new1); n1.RemoveFromGraph(); new1.Next = new2; new2.Next = n2.Next; n2.RemoveFromGraph(); } else if (i < body.Count - 2) { Node n3 = body[i + 2]; if (i < body.Count - 3) { Node n4 = body[i + 3]; if (detectedOperandExchange(n1, n2, n3, n4)) { result = flag = true; Node n = newDuplicateStackTop(block); body[i] = n; body[i + 1] = n1; body[i + 2] = n2; body[i + 3] = n4; n3.RemoveFromGraph(); n1.ReplaceByNode(n); n.Next = n1; n2.Next = n4; } else if (detectedQuadruple1(n1, n2, n3, n4)) { result = flag = true; Node n = newDuplicateStackTop(block); body[i] = n; body[i + 1] = n1; body[i + 2] = n2; body[i + 3] = n3; n1.ReplaceByNode(n); n.Next = n1; n3.Next = n4.Next; n4.RemoveFromGraph(); } } } } } } } return(result); }
public LoadVar this [StoreVar storer] { get { return(usageHash[storer] as LoadVar); } }
public bool IsUsed(StoreVar storer) { return(usageHash.ContainsKey(storer)); }
internal void addUsage(StoreVar storer, LoadVar loader) { usageHash.Add(storer, loader); }
private bool performConstantAliasesRemoval() { bool result = false; foreach (Variable v in mbb.Variables) { if (varIsNotReferenced(v) && v.Kind == VariableKind.Local) { Node varUseNode = null; int count = 0; foreach (Node node in v.UsersArray) { if (node is StoreVar) { varUseNode = node; count++; } } if (count == 1) { BasicBlock block = varUseNode.Options[BasicBlock.BASIC_BLOCK_OPTION] as BasicBlock; Node prevNode = varUseNode.PrevArray[0]; while (prevNode is DuplicateStackTop && prevNode.Options[BasicBlock.BASIC_BLOCK_OPTION] == block) { prevNode = prevNode.PrevArray[0]; } if (prevNode is LoadConst && prevNode.Options[BasicBlock.BASIC_BLOCK_OPTION] == block) { result = true; StoreVar stNode = varUseNode as StoreVar; LoadConst ldNode = prevNode as LoadConst; NodeArray aliasUsageList = new NodeArray(); foreach (Node node in stNode.Var.UsersArray) { if (node is LoadVar) { aliasUsageList.Add(node); } } replaceNodeByPop(stNode); stNode.RemoveFromGraph(); foreach (LoadVar node in aliasUsageList) { Node n = ldNode.Clone(); BasicBlock blk = node.Options[BasicBlock.BASIC_BLOCK_OPTION] as BasicBlock; n.Options[BasicBlock.BASIC_BLOCK_OPTION] = blk; blk.Body[blk.Body.IndexOf(node)] = n; node.ReplaceByNode(n); n.Next = node.Next; node.RemoveFromGraph(); } } } } } return(result); }
protected internal virtual void VisitStoreVar(StoreVar node, object data) { throw new NodeNotSupportedException(node); }
protected override void VisitStoreVar(StoreVar downNode, object o) { PointerValue ptr = new PointerToLocationValue(this.state.Pool[downNode.Var]); this.storeVar(downNode, ptr, o); }
private void callMethod(Node downNode, AnnotatedMethod method, PointerToNode ptrUpNode, Node upNode, Value[] args) { if (method.SourceMethod.IsDefined(typeof(InlineAttribute), false) && !(upNode is NewObject)) { MethodBodyBlock mbbDown = this.holder.AnnotatedHolder[method]; SpecState state = new SpecState(mbbDown.Variables.Count); int varCount = 0; int argCount = 0; foreach (Variable varDown in mbbDown.Variables.ParameterMapper) { state.Pool[varDown] = new Location(varDown.Type); Variable varUp = this.mbbUp.Variables.CreateVar(varDown.Type, VariableKind.Local); this.varsHash[new PointerToLocationValue(state.Pool[varDown])] = varUp; if (Annotation.GetValueBTType(method.ParamVals[varCount++].Val) == BTType.Static) { state.Pool[varDown].Val = args[argCount]; state.Stack.Push(args[argCount++]); } else { Node upNext = new StoreVar(varUp); Node upPrevNext = ptrUpNode.Node; ptrUpNode.Node = upNext; upNext.Next = upPrevNext; } } while (ptrUpNode.Node != null) { ptrUpNode = new PointerToNode(ptrUpNode.Node); } foreach (Variable varDown in mbbDown.Variables) { if (!state.Pool.ContainsVar(varDown)) { state.Pool[varDown] = new Location(varDown.Type); Variable varUp = this.mbbUp.Variables.CreateVar(varDown.Type, VariableKind.Local); this.varsHash[new PointerToLocationValue(state.Pool[varDown])] = varUp; ptrUpNode = SpecializingVisitor.initVariable(varUp, ptrUpNode); } } int depth = state.Stack.Count + 1; GraphProcessor graphProc = new GraphProcessor(); SpecializingVisitor visitor = new SpecializingVisitor(graphProc, this.holder, this.mbbUp, state, this.varsHash); visitor.AddTask(mbbDown.Next, ptrUpNode); graphProc.Process(); foreach (Data newData in visitor.exitData) { state.Recall(newData.MemoSpecState, newData.ObjectHashtable); if (state.Stack.Count == depth) { this.state.Stack.Push(state.Stack.Pop()); } this.AddTask(downNode.Next, newData.PointerToNode); } } else { ObjectHashtable objHash = new ObjectHashtable(); MemoState memoArgs = new MemoState(args, objHash); PointerValue[] ptrs = this.varsHash.GetPointers(objHash); for (int i = 0; i < ptrs.Length; i++) { ptrUpNode = new PointerToNode(ptrUpNode.Node = new LoadVarAddr(this.varsHash[ptrs[i]])); } ptrUpNode = new PointerToNode(ptrUpNode.Node = upNode); ResidualMethod callMethod = new ResidualMethod(method, memoArgs, args, ptrs); Specialization.SetResidualMethod(upNode, callMethod); this.holder.SpecializeMethod(callMethod); this.AddTask(downNode.Next, ptrUpNode); } }
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); }