protected internal override void VisitLoadConst(LoadConst node, object data) { StackTypes stack = data as StackTypes; if (node.Constant == null) { stack.Push(null); } else { stack.Push(node.Constant.GetType()); } AddTask(node.Next, stack); }
protected override void VisitLoadConst(LoadConst node, object data) { state.Stack.Perform_LoadConst(node.Constant); nextNode = node.Next; }
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); }
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 VisitLoadConst(LoadConst node, object data) { throw new NodeNotSupportedException(node); }
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); }