Ejemplo n.º 1
0
 protected static BasicBlock ExtractAsBasicBlock(BasicBlock b, int i, int j)
 {
     List<IStatement> statements = b.Statements;
       BasicBlock result = new BasicBlock(0);
       if (b.LocalVariables != null)
     result.LocalVariables = new List<ILocalDefinition>(b.LocalVariables);
       while (i < j) {
     var s = statements[i++];
     MoveTempIfNecessary(b, result, s);
     result.Statements.Add(s);
       }
       return result;
 }
Ejemplo n.º 2
0
 protected static BasicBlock GetBasicBlockStartingAt(BasicBlock bb, uint offset)
 {
     while (bb.StartOffset < offset && bb.Statements.Count > 0) {
     BasicBlock bbb = bb.Statements[bb.Statements.Count-1] as BasicBlock;
     if (bbb == null) return new BasicBlock(offset);
     if (bbb.StartOffset == offset) {
       bb.Statements.RemoveAt(bb.Statements.Count-1);
       return bbb;
     }
     bb = bbb;
       }
       return bb;
 }
Ejemplo n.º 3
0
 internal void Traverse(SourceMethodBody body, BasicBlock rootBlock)
 {
     this.Traverse(rootBlock);
       //Now add declarations for any locals declared only on the body (for example temporary variables introduced by Unstacker).
       List<IStatement> prelude = new List<IStatement>();
       var localsAndTemps = body.localVariablesAndTemporaries;
       this.AddDeclarationsWithInitialValues(localsAndTemps, rootBlock);
       foreach (var localDef in localsAndTemps) {
     if (this.declaredLocals.ContainsKey(localDef)) continue;
     LocalDeclarationStatement localDecl = new LocalDeclarationStatement();
     localDecl.LocalVariable = localDef;
     prelude.Add(localDecl);
       }
       if (prelude.Count > 0)
     rootBlock.Statements.InsertRange(0, prelude); //TODO: use pdb info to insert them in the same order they appear in the source
 }
Ejemplo n.º 4
0
 private void Flatten(BasicBlock blockStatement, List<IStatement> flatListOfStatements)
 {
     foreach (IStatement statement in blockStatement.Statements){
     BasicBlock/*?*/ nestedBlock = statement as BasicBlock;
     if (nestedBlock != null) {
       if (nestedBlock.LocalVariables == null || nestedBlock.LocalVariables.Count == 0 || nestedBlock.Statements.Count == 0 || (nestedBlock.Statements.Count == 1 && nestedBlock.Statements[0] is BasicBlock))
     this.Flatten(nestedBlock, flatListOfStatements);
       else {
     this.Traverse(nestedBlock);
     flatListOfStatements.Add(nestedBlock);
       }
     } else {
       this.Traverse(statement);
       flatListOfStatements.Add(statement);
     }
       }
 }
Ejemplo n.º 5
0
 protected static BasicBlock GetBasicBlockUpto(BasicBlock b, uint endOffset)
 {
     BasicBlock result = new BasicBlock(b.StartOffset);
       if (b.LocalVariables != null)
     result.LocalVariables = new List<ILocalDefinition>(b.LocalVariables);
       result.EndOffset = endOffset;
       int n = b.Statements.Count;
       for (int i = 0; i < n-1; i++) {
     var s = b.Statements[i];
     MoveTempIfNecessary(b, result, s);
     result.Statements.Add(b.Statements[i]);
       }
       if (n > 0) {
     b.Statements.RemoveRange(0, n-1);
     BasicBlock bb = (BasicBlock)b.Statements[0];
     if (bb.StartOffset < endOffset)
       result.Statements.Add(GetBasicBlockUpto(bb, endOffset));
       }
       return result;
 }
Ejemplo n.º 6
0
        // For the first assignment to a local variable in a block before a control statement is hit,
        // if the local variable is not mentioned previously, we turn this assignment into a local declaration.
        private void AddDeclarationsWithInitialValues(IEnumerable <ILocalDefinition> localVariables, BasicBlock block)
        {
            List <ILocalDefinition> topLevelLocals = new List <ILocalDefinition>(localVariables);
            List <ILocalDefinition> localsMet      = new List <ILocalDefinition>();

            for (int i = 0; i < block.Statements.Count; i++)
            {
                if (topLevelLocals.Count == 0)
                {
                    break;
                }
                IExpressionStatement expressionStatement = block.Statements[i] as IExpressionStatement;
                if (expressionStatement != null)
                {
                    IAssignment assignment = expressionStatement.Expression as IAssignment;
                    if (assignment != null)
                    {
                        ILocalDefinition localDef = assignment.Target.Definition as ILocalDefinition;
                        if (localDef != null && topLevelLocals.Contains(localDef) && !localsMet.Contains(localDef) && !this.declaredLocals.ContainsKey(localDef))
                        {
                            LocalDeclarationStatement localDecl = new LocalDeclarationStatement()
                            {
                                LocalVariable = localDef, InitialValue = assignment.Source, Locations = new List <ILocation>(expressionStatement.Locations),
                            };
                            this.declaredLocals.Add(localDef, true);
                            block.Statements[i] = localDecl;
                            topLevelLocals.Remove(localDef);
                            localsMet.Add(localDef);
                        }
                    }
                }
                LocalFinder finder = new LocalFinder();
                finder.Traverse(block.Statements[i]);
                foreach (ILocalDefinition local in finder.FoundLocals)
                {
                    if (!localsMet.Contains(local))
                    {
                        localsMet.Add(local);
                    }
                }
                //Once we see a statement that can transfer control somewhere else, we
                //no longer know that any subsequent assignment dominates all references
                //and hence cannot postpone adding the declaration until we can unify it with the assignment.
                IGotoStatement gotoStatement = block.Statements[i] as IGotoStatement;
                if (gotoStatement != null)
                {
                    break;
                }
                IConditionalStatement conditionalStatement = block.Statements[i] as IConditionalStatement;
                if (conditionalStatement != null)
                {
                    break;
                }
                ISwitchStatement switchStatement = block.Statements[i] as ISwitchStatement;
                if (switchStatement != null)
                {
                    break;
                }
                IForEachStatement foreachStatement = block.Statements[i] as IForEachStatement;
                if (foreachStatement != null)
                {
                    break;
                }
                IForStatement forStatement = block.Statements[i] as IForStatement;
                if (forStatement != null)
                {
                    break;
                }
                ITryCatchFinallyStatement tryStatement = block.Statements[i] as ITryCatchFinallyStatement;
                if (tryStatement != null)
                {
                    break;
                }
            }
        }
Ejemplo n.º 7
0
 private void Traverse(BasicBlock b)
 {
     this.blockLocalVariables = b.LocalVariables;
       for (int i = 0; i < b.Statements.Count; i++) {
     this.DeleteGotoNextStatement(b.Statements, i);
     this.ReplaceLocalArrayInitializerPattern(b.Statements, i);
     this.ReplaceShortCircuitPattern(b.Statements, i);
     this.ReplaceShortCircuitPattern2(b.Statements, i);
     this.ReplacePushPopPattern(b.Statements, i);
       }
       if (this.blockLocalVariables != b.LocalVariables)
     b.LocalVariables = this.blockLocalVariables;
 }
Ejemplo n.º 8
0
 private void TurnOperandStackIntoPushStatements(BasicBlock currentBlock)
 {
     int insertPoint = currentBlock.Statements.Count;
       while (this.operandStack.Count > 0) {
     Expression operand = this.PopOperandStack();
     MethodCall/*?*/ call = operand as MethodCall;
     if (call != null && call.MethodToCall.Type.TypeCode == PrimitiveTypeCode.Void) {
       ExpressionStatement expressionStatement = new ExpressionStatement();
       expressionStatement.Expression = operand;
       currentBlock.Statements.Insert(insertPoint, expressionStatement);
     } else {
       PushStatement push = new PushStatement();
       push.ValueToPush = operand;
       currentBlock.Statements.Insert(insertPoint, push);
     }
       }
 }
Ejemplo n.º 9
0
 private static IExpression ExtractFilterCondition(BasicBlock handlerBlock)
 {
     int endFilterIndex = -1;
       IExpression result = CodeDummy.Expression;
       for (int i = 0; i < handlerBlock.Statements.Count; i++) {
     var endFilter = handlerBlock.Statements[i] as EndFilter;
     if (endFilter != null) {
       result = endFilter.FilterResult;
       endFilterIndex = i;
       break;
     }
       }
       if (endFilterIndex < 0) return result;
       if (endFilterIndex == 0) {
     handlerBlock.Statements.RemoveAt(0);
     return result;
       }
       var blockExpression = new BlockExpression();
       blockExpression.BlockStatement = ExtractAsBasicBlock(handlerBlock, 0, endFilterIndex);
       blockExpression.Expression = result;
       blockExpression.Type = result.Type;
       handlerBlock.Statements.RemoveRange(0, endFilterIndex+1);
       return blockExpression;
 }
Ejemplo n.º 10
0
 private void FindLastUsesOfLocals(BasicBlock<Instruction> bb) {
   Contract.Requires(bb != null);
   for (int i = 0, n = bb.Instructions.Count; i < n; i++) {
     Contract.Assume(i < bb.Instructions.Count);
     var instruction = bb.Instructions[i];
     switch (instruction.Operation.OperationCode) {
       case OperationCode.Ldloc:
       case OperationCode.Ldloc_0:
       case OperationCode.Ldloc_1:
       case OperationCode.Ldloc_2:
       case OperationCode.Ldloc_3:
       case OperationCode.Ldloc_S:
       case OperationCode.Ldloca:
       case OperationCode.Ldloca_S:
         var local = (ILocalDefinition)instruction.Operation.Value;
         if (this.NextReferenceIsAssignment(local, bb, i+1, new SetOfObjects()))
           this.instructionsThatMakeALastUseOfALocalVersion.Add(instruction);
         break;
     }
   }
 }
Ejemplo n.º 11
0
        /// <summary>
        /// Parse instructions and put them into an expression tree until an assignment, void call, branch target, or branch is encountered.
        /// Returns true if the parsed statement is last of the current basic block. This happens when the next statement is a branch
        /// target, or if the parsed statement could transfers control to anything but the following statement.
        /// </summary>
        private void ParseInstruction(BasicBlock currentBlock)
        {
            Statement/*?*/ statement = null;
              Expression/*?*/ expression = null;
              IOperation currentOperation = this.operationEnumerator.Current;
              OperationCode currentOpcode = currentOperation.OperationCode;
              if (this.host.PreserveILLocations) {
            if (this.lastLocation == null)
              this.lastLocation = currentOperation.Location;
              } else {
            if (this.sourceLocationProvider != null && this.lastSourceLocation == null) {
              foreach (var sourceLocation in this.sourceLocationProvider.GetPrimarySourceLocationsFor(currentOperation.Location)) {
            if (sourceLocation.StartLine != 0x00feefee) {
              this.lastSourceLocation = sourceLocation;
              break;
            }
              }
            }
              }
              switch (currentOpcode) {
            case OperationCode.Add:
            case OperationCode.Add_Ovf:
            case OperationCode.Add_Ovf_Un:
            case OperationCode.And:
            case OperationCode.Ceq:
            case OperationCode.Cgt:
            case OperationCode.Cgt_Un:
            case OperationCode.Clt:
            case OperationCode.Clt_Un:
            case OperationCode.Div:
            case OperationCode.Div_Un:
            case OperationCode.Mul:
            case OperationCode.Mul_Ovf:
            case OperationCode.Mul_Ovf_Un:
            case OperationCode.Or:
            case OperationCode.Rem:
            case OperationCode.Rem_Un:
            case OperationCode.Shl:
            case OperationCode.Shr:
            case OperationCode.Shr_Un:
            case OperationCode.Sub:
            case OperationCode.Sub_Ovf:
            case OperationCode.Sub_Ovf_Un:
            case OperationCode.Xor:
              expression = this.ParseBinaryOperation(currentOpcode);
              break;

            case OperationCode.Arglist:
              expression = new RuntimeArgumentHandleExpression();
              break;

            case OperationCode.Array_Addr:
            case OperationCode.Ldelema:
              expression = this.ParseArrayElementAddres(currentOperation);
              break;

            case OperationCode.Array_Create:
            case OperationCode.Array_Create_WithLowerBound:
            case OperationCode.Newarr:
              expression = this.ParseArrayCreate(currentOperation);
              break;

            case OperationCode.Array_Get:
            case OperationCode.Ldelem:
            case OperationCode.Ldelem_I:
            case OperationCode.Ldelem_I1:
            case OperationCode.Ldelem_I2:
            case OperationCode.Ldelem_I4:
            case OperationCode.Ldelem_I8:
            case OperationCode.Ldelem_R4:
            case OperationCode.Ldelem_R8:
            case OperationCode.Ldelem_Ref:
            case OperationCode.Ldelem_U1:
            case OperationCode.Ldelem_U2:
            case OperationCode.Ldelem_U4:
              expression = this.ParseArrayIndexer(currentOperation);
              break;

            case OperationCode.Array_Set:
              statement = this.ParseArraySet(currentOperation);
              break;

            case OperationCode.Beq:
            case OperationCode.Beq_S:
            case OperationCode.Bge:
            case OperationCode.Bge_S:
            case OperationCode.Bge_Un:
            case OperationCode.Bge_Un_S:
            case OperationCode.Bgt:
            case OperationCode.Bgt_S:
            case OperationCode.Bgt_Un:
            case OperationCode.Bgt_Un_S:
            case OperationCode.Ble:
            case OperationCode.Ble_S:
            case OperationCode.Ble_Un:
            case OperationCode.Ble_Un_S:
            case OperationCode.Blt:
            case OperationCode.Blt_S:
            case OperationCode.Blt_Un:
            case OperationCode.Blt_Un_S:
            case OperationCode.Bne_Un:
            case OperationCode.Bne_Un_S:
              statement = this.ParseBinaryConditionalBranch(currentOperation);
              break;

            case OperationCode.Box:
              expression = this.ParseConversion(currentOperation);
              break;

            case OperationCode.Br:
            case OperationCode.Br_S:
            case OperationCode.Leave:
            case OperationCode.Leave_S:
              statement = this.ParseUnconditionalBranch(currentOperation);
              break;

            case OperationCode.Break:
              statement = new DebuggerBreakStatement();
              break;

            case OperationCode.Brfalse:
            case OperationCode.Brfalse_S:
            case OperationCode.Brtrue:
            case OperationCode.Brtrue_S:
              statement = this.ParseUnaryConditionalBranch(currentOperation);
              break;

            case OperationCode.Call:
            case OperationCode.Callvirt:
              MethodCall call = this.ParseCall(currentOperation);
              if (call.MethodToCall.Type.TypeCode == PrimitiveTypeCode.Void) {
            call.Locations.Add(currentOperation.Location); // turning it into a statement prevents the location from being attached to the expresssion
            ExpressionStatement es = new ExpressionStatement();
            es.Expression = call;
            statement = es;
              } else
            expression = call;
              break;

            case OperationCode.Calli:
              expression = this.ParsePointerCall(currentOperation);
              break;

            case OperationCode.Castclass:
            case OperationCode.Conv_I:
            case OperationCode.Conv_I1:
            case OperationCode.Conv_I2:
            case OperationCode.Conv_I4:
            case OperationCode.Conv_I8:
            case OperationCode.Conv_Ovf_I:
            case OperationCode.Conv_Ovf_I_Un:
            case OperationCode.Conv_Ovf_I1:
            case OperationCode.Conv_Ovf_I1_Un:
            case OperationCode.Conv_Ovf_I2:
            case OperationCode.Conv_Ovf_I2_Un:
            case OperationCode.Conv_Ovf_I4:
            case OperationCode.Conv_Ovf_I4_Un:
            case OperationCode.Conv_Ovf_I8:
            case OperationCode.Conv_Ovf_I8_Un:
            case OperationCode.Conv_Ovf_U:
            case OperationCode.Conv_Ovf_U_Un:
            case OperationCode.Conv_Ovf_U1:
            case OperationCode.Conv_Ovf_U1_Un:
            case OperationCode.Conv_Ovf_U2:
            case OperationCode.Conv_Ovf_U2_Un:
            case OperationCode.Conv_Ovf_U4:
            case OperationCode.Conv_Ovf_U4_Un:
            case OperationCode.Conv_Ovf_U8:
            case OperationCode.Conv_Ovf_U8_Un:
            case OperationCode.Conv_R_Un:
            case OperationCode.Conv_R4:
            case OperationCode.Conv_R8:
            case OperationCode.Conv_U:
            case OperationCode.Conv_U1:
            case OperationCode.Conv_U2:
            case OperationCode.Conv_U4:
            case OperationCode.Conv_U8:
            case OperationCode.Unbox:
            case OperationCode.Unbox_Any:
              expression = this.ParseConversion(currentOperation);
              break;

            case OperationCode.Ckfinite:
              this.PopOperandStack();
              Debug.Assert(false); //if code out there actually uses this, I need to know sooner rather than later.
              //TODO: need a code model statement for this instruction.
              break;

            case OperationCode.Constrained_:
              //This prefix is redundant and is not represented in the code model.
              break;

            case OperationCode.Cpblk:
              var copyMemory = new CopyMemoryStatement();
              copyMemory.NumberOfBytesToCopy = this.PopOperandStack();
              copyMemory.SourceAddress = this.PopOperandStack();
              copyMemory.TargetAddress = this.PopOperandStack();
              statement = copyMemory;
              break;

            case OperationCode.Cpobj:
              expression = this.ParseCopyObject();
              break;

            case OperationCode.Dup:
              statement = this.ParseDup();
              break;

            case OperationCode.Endfilter:
              statement = this.ParseEndfilter();
              break;

            case OperationCode.Endfinally:
              statement = new EndFinally();
              break;

            case OperationCode.Initblk:
              var fillMemory = new FillMemoryStatement();
              fillMemory.NumberOfBytesToFill = this.PopOperandStack();
              fillMemory.FillValue = this.PopOperandStack();
              fillMemory.TargetAddress = this.PopOperandStack();
              statement = fillMemory;
              break;

            case OperationCode.Initobj:
              statement = this.ParseInitObject(currentOperation);
              break;

            case OperationCode.Isinst:
              expression = this.ParseCastIfPossible(currentOperation);
              break;

            case OperationCode.Jmp:
              Debug.Assert(false); //if code out there actually uses this, I need to know sooner rather than later.
              //TODO: need a code model statement for this instruction.
              break;

            case OperationCode.Ldarg:
            case OperationCode.Ldarg_0:
            case OperationCode.Ldarg_1:
            case OperationCode.Ldarg_2:
            case OperationCode.Ldarg_3:
            case OperationCode.Ldarg_S:
            case OperationCode.Ldloc:
            case OperationCode.Ldloc_0:
            case OperationCode.Ldloc_1:
            case OperationCode.Ldloc_2:
            case OperationCode.Ldloc_3:
            case OperationCode.Ldloc_S:
            case OperationCode.Ldfld:
            case OperationCode.Ldsfld:
              expression = this.ParseBoundExpression(currentOperation);
              break;

            case OperationCode.Ldarga:
            case OperationCode.Ldarga_S:
            case OperationCode.Ldflda:
            case OperationCode.Ldsflda:
            case OperationCode.Ldloca:
            case OperationCode.Ldloca_S:
            case OperationCode.Ldftn:
            case OperationCode.Ldvirtftn:
              expression = this.ParseAddressOf(currentOperation);
              break;

            case OperationCode.Ldc_I4:
            case OperationCode.Ldc_I4_0:
            case OperationCode.Ldc_I4_1:
            case OperationCode.Ldc_I4_2:
            case OperationCode.Ldc_I4_3:
            case OperationCode.Ldc_I4_4:
            case OperationCode.Ldc_I4_5:
            case OperationCode.Ldc_I4_6:
            case OperationCode.Ldc_I4_7:
            case OperationCode.Ldc_I4_8:
            case OperationCode.Ldc_I4_M1:
            case OperationCode.Ldc_I4_S:
            case OperationCode.Ldc_I8:
            case OperationCode.Ldc_R4:
            case OperationCode.Ldc_R8:
            case OperationCode.Ldnull:
            case OperationCode.Ldstr:
              expression = this.ParseCompileTimeConstant(currentOperation);
              break;

            case OperationCode.Ldind_I:
            case OperationCode.Ldind_I1:
            case OperationCode.Ldind_I2:
            case OperationCode.Ldind_I4:
            case OperationCode.Ldind_I8:
            case OperationCode.Ldind_R4:
            case OperationCode.Ldind_R8:
            case OperationCode.Ldind_Ref:
            case OperationCode.Ldind_U1:
            case OperationCode.Ldind_U2:
            case OperationCode.Ldind_U4:
            case OperationCode.Ldobj:
              expression = this.ParseAddressDereference(currentOperation);
              break;

            case OperationCode.Ldlen:
              expression = this.ParseVectorLength();
              break;

            case OperationCode.Ldtoken:
              expression = ParseToken(currentOperation);
              break;

            case OperationCode.Localloc:
              expression = this.ParseStackArrayCreate();
              break;

            case OperationCode.Mkrefany:
              expression = this.ParseMakeTypedReference(currentOperation);
              break;

            case OperationCode.Neg:
              expression = this.ParseUnaryOperation(new UnaryNegation());
              break;

            case OperationCode.Not:
              expression = this.ParseUnaryOperation(new OnesComplement());
              break;

            case OperationCode.Newobj:
              expression = this.ParseCreateObjectInstance(currentOperation);
              break;

            case OperationCode.No_:
              Debug.Assert(false); //if code out there actually uses this, I need to know sooner rather than later.
              //TODO: need object model support
              break;

            case OperationCode.Nop:
              statement = new EmptyStatement();
              break;

            case OperationCode.Pop:
              statement = this.ParsePop();
              break;

            case OperationCode.Readonly_:
              this.sawReadonly = true;
              break;

            case OperationCode.Refanytype:
              expression = this.ParseGetTypeOfTypedReference();
              break;

            case OperationCode.Refanyval:
              expression = this.ParseGetValueOfTypedReference(currentOperation);
              break;

            case OperationCode.Ret:
              statement = this.ParseReturn();
              break;

            case OperationCode.Rethrow:
              statement = new RethrowStatement();
              break;

            case OperationCode.Sizeof:
              expression = ParseSizeOf(currentOperation);
              break;

            case OperationCode.Starg:
            case OperationCode.Starg_S:
            case OperationCode.Stelem:
            case OperationCode.Stelem_I:
            case OperationCode.Stelem_I1:
            case OperationCode.Stelem_I2:
            case OperationCode.Stelem_I4:
            case OperationCode.Stelem_I8:
            case OperationCode.Stelem_R4:
            case OperationCode.Stelem_R8:
            case OperationCode.Stelem_Ref:
            case OperationCode.Stfld:
            case OperationCode.Stind_I:
            case OperationCode.Stind_I1:
            case OperationCode.Stind_I2:
            case OperationCode.Stind_I4:
            case OperationCode.Stind_I8:
            case OperationCode.Stind_R4:
            case OperationCode.Stind_R8:
            case OperationCode.Stind_Ref:
            case OperationCode.Stloc:
            case OperationCode.Stloc_0:
            case OperationCode.Stloc_1:
            case OperationCode.Stloc_2:
            case OperationCode.Stloc_3:
            case OperationCode.Stloc_S:
            case OperationCode.Stobj:
            case OperationCode.Stsfld:
              statement = this.ParseAssignment(currentOperation);
              break;

            case OperationCode.Switch:
              statement = this.ParseSwitchInstruction(currentOperation);
              break;

            case OperationCode.Tail_:
              this.sawTailCall = true;
              break;

            case OperationCode.Throw:
              statement = this.ParseThrow();
              break;

            case OperationCode.Unaligned_:
              this.alignment = (byte)currentOperation.Value;
              break;

            case OperationCode.Volatile_:
              this.sawVolatile = true;
              break;

              }
              if (expression != null) {
            if (this.host.PreserveILLocations) {
              expression.Locations.Add(currentOperation.Location);
            }
            this.operandStack.Push(expression);
              } else if (statement != null) {
            this.TurnOperandStackIntoPushStatements(currentBlock);
            currentBlock.Statements.Add(statement);
            if (this.host.PreserveILLocations) {
              if (this.lastLocation != null) {
            statement.Locations.Add(this.lastLocation);
            this.lastLocation = null;
              }
            } else if (this.lastSourceLocation != null) {
              statement.Locations.Add(this.lastSourceLocation);
              this.lastSourceLocation = null;
            }
              }
        }
Ejemplo n.º 12
0
 public override void TraverseChildren(IGotoStatement gotoStatement)
 {
     if (gotoStatement == this.backwardsBranch) {
     if (this.currentIf != null && this.currentIf.TrueBranch == this.currentBlock && this.currentIf.FalseBranch is EmptyStatement) {
       this.ifContainingBackwardsBranch = this.currentIf;
       this.blockContainingIfContainingBackwardsBranch = this.blockContainingCurrentIf;
     }
       }
       this.gotosAlreadyTraversed.Add(gotoStatement);
       base.TraverseChildren(gotoStatement);
 }
Ejemplo n.º 13
0
 internal static uint GetStartOffset(BasicBlock<Instruction> basicBlock) {
   Contract.Assume(basicBlock != null);
   Contract.Assume(basicBlock.Instructions.Count > 0);
   return basicBlock.Instructions[0].Operation.Offset;
 }
Ejemplo n.º 14
0
 public override void TraverseChildren(IBlockStatement block)
 {
     var savedCurrentBlock = this.currentBlock;
       var bb = (BasicBlock)block;
       this.currentBlock = bb;
       while (true) {
     var n = bb.Statements.Count;
     if (n == 0) break;
     for (int i = 0; i < n-1; i++)
       this.Traverse(bb.Statements[i]);
     var bbb = bb.Statements[n-1] as BasicBlock;
     if (bbb == null || this.loopHeader == null) {
       this.Traverse(bb.Statements[n-1]);
       break;
     }
     bb = bbb;
       }
       this.Traverse(this.currentBlock);
       this.currentBlock = savedCurrentBlock;
 }
Ejemplo n.º 15
0
 public override void TraverseChildren(IConditionalStatement conditionalStatement)
 {
     this.currentIf = conditionalStatement;
       this.blockContainingCurrentIf = this.currentBlock;
       base.TraverseChildren(conditionalStatement);
 }
Ejemplo n.º 16
0
 private void DecompileTryBody(BasicBlock b, BasicBlock firstHandler, TryCatchFinallyStatement tryStatement)
 {
     tryStatement.TryBody = GetBasicBlockUpto(b, firstHandler.StartOffset);
       BasicBlock tryBody = tryStatement.TryBody as BasicBlock;
       int startPoint = 0;
       if (tryBody != null && tryBody.Statements.Count > 0) {
     ILabeledStatement labeledStatement = tryBody.Statements[0] as ILabeledStatement;
     if (labeledStatement != null) {
       tryBody.Statements.RemoveAt(0);
       b.Statements.Insert(startPoint, labeledStatement);
       startPoint++;
     }
       }
       b.Statements.Insert(startPoint, tryStatement);
 }
Ejemplo n.º 17
0
 private static void DecompileHandler(BasicBlock containingBlock, BasicBlock handlerBlock, TryCatchFinallyStatement tryStatement)
 {
     if (handlerBlock.ExceptionInformation.HandlerKind == HandlerKind.Finally) {
     tryStatement.FinallyBody = handlerBlock;
       } else if (handlerBlock.ExceptionInformation.HandlerKind == HandlerKind.Fault) {
     tryStatement.FaultBody = handlerBlock;
       } else {
     CatchClause catchClause = new CatchClause();
     catchClause.Body = handlerBlock;
     catchClause.ExceptionType = handlerBlock.ExceptionInformation.ExceptionType;
     if (handlerBlock.ExceptionInformation.HandlerKind == HandlerKind.Catch) {
       catchClause.ExceptionContainer = ExtractExceptionContainer(handlerBlock);
     } else if (handlerBlock.ExceptionInformation.HandlerKind == HandlerKind.Filter) {
       catchClause.FilterCondition = ExtractFilterCondition(handlerBlock);
     }
     tryStatement.CatchClauses.Add(catchClause);
       }
       //Remove handler from statements in containing block
       containingBlock.Statements[containingBlock.Statements.Count-1] = GetBasicBlockStartingAt(handlerBlock, handlerBlock.ExceptionInformation.HandlerEndOffset);
       RemoveEndFinally(handlerBlock);
 }
Ejemplo n.º 18
0
 private static void RemoveEndFinally(BasicBlock handlerBlock)
 {
     while (handlerBlock != null) {
     int i = handlerBlock.Statements.Count-1;
     if (i < 0) return;
     if (handlerBlock.Statements[i] is EndFinally) {
       handlerBlock.Statements.RemoveAt(i);
       return;
     } else {
       handlerBlock = handlerBlock.Statements[i] as BasicBlock;
     }
       }
 }
Ejemplo n.º 19
0
 protected override void Traverse(BasicBlock b)
 {
     for (int i = 0; i < b.Statements.Count; i++) {
     this.DecompileSwitch(b.Statements, i);
       }
 }
Ejemplo n.º 20
0
 public override void TraverseChildren(ILabeledStatement labeledStatement)
 {
     if (this.loopHeader == null) {
     List<IGotoStatement> predecessors;
     if (this.predecessors.TryGetValue(labeledStatement, out predecessors)) {
       if (predecessors.Count == 1 && !this.gotosAlreadyTraversed.Contains(predecessors[0])) {
     this.blockContainingLoopHeader = this.currentBlock;
     this.loopHeader = labeledStatement;
     this.backwardsBranch = predecessors[0];
     this.ifContainingBackwardsBranch = null;
       }
     }
       }
       base.TraverseChildren(labeledStatement);
 }
Ejemplo n.º 21
0
 internal void Traverse(BasicBlock rootBlock)
 {
     this.secondPass = false;
       this.Traverse((IBlockStatement)rootBlock);
       this.secondPass = true;
       this.Traverse((IBlockStatement)rootBlock);
 }
Ejemplo n.º 22
0
 protected override void Traverse(BasicBlock b)
 {
     if (b == this.blockContainingLoopHeader && this.ifContainingBackwardsBranch != null && this.blockContainingIfContainingBackwardsBranch == b) {
     int i = 0;
     while (b.Statements[i] != this.loopHeader) i++;
     var loopBody = this.ExtractBasicBlockUpto(b, i+1, this.ifContainingBackwardsBranch);
     b.Statements[i] = new WhileDoStatement() { Body = loopBody, Condition = this.ifContainingBackwardsBranch.Condition};
     RemoveStatement(b, this.ifContainingBackwardsBranch);
     new WhileLoopDecompiler(this.platformType, this.predecessors).Traverse(loopBody);
       }
 }
Ejemplo n.º 23
0
 private void ParseBasicBlock(List<IStatement> list, BasicBlock<Instruction> bb) {
   Contract.Requires(list != null);
   Contract.Requires(bb != null);
   this.FindLastUsesOfLocals(bb);
   this.operandStack.Clear();
   foreach (var stackSetupInstruction in bb.OperandStack) {
     Contract.Assume(stackSetupInstruction != null);
     Contract.Assume(!(stackSetupInstruction.Type is Dummy));
     this.operandStack.Push(new PopValue() { Type = stackSetupInstruction.Type });
   }
   if (bb.Instructions.Count > 0) { //It might be 0 if there are no il instructions, which happens for some kinds of reference assemblies.
     var label = this.GetTargetStatement(bb.Instructions[0].Operation.Offset);
     list.Add(label);
     foreach (var instruction in bb.Instructions) {
       Contract.Assume(instruction != null);
       this.ParseInstruction(instruction, list);
     }
   }
   if (list.Count > 0 && !(list[list.Count-1] is GotoStatement))
     this.TurnOperandStackIntoPushStatements(list);
 }
Ejemplo n.º 24
0
 protected override void Traverse(BasicBlock b)
 {
     if (b.NumberOfTryBlocksStartingHere > 0) {
     BasicBlock firstHandler = null;
     TryCatchFinallyStatement/*?*/ tryStatement = new TryCatchFinallyStatement();
     BasicBlock bb = b;
     while (b.NumberOfTryBlocksStartingHere-- > 0) {
       if (bb.Statements.Count > 0) {
     BasicBlock bbb = bb.Statements[bb.Statements.Count-1] as BasicBlock;
     while (bbb != null) {
       if (bbb.ExceptionInformation != null) {
         if (firstHandler == null) firstHandler = bbb;
         if (firstHandler.ExceptionInformation.TryEndOffset < bbb.ExceptionInformation.TryEndOffset) {
           DecompileTryBody(b, firstHandler, tryStatement);
           tryStatement = new TryCatchFinallyStatement();
           firstHandler = bbb;
         }
         DecompileHandler(bb, bbb, tryStatement);
         break;
       }
       if (bbb.Statements.Count == 0) break;
       bb = bbb;
       bbb = bbb.Statements[bbb.Statements.Count-1] as BasicBlock;
     }
       }
     }
     DecompileTryBody(b, firstHandler, tryStatement);
       }
 }
Ejemplo n.º 25
0
    private bool NextReferenceIsAssignment(ILocalDefinition local, BasicBlock<Instruction> bb, int offset, SetOfObjects blocksAlreadyVisited) {
      Contract.Requires(bb != null);
      Contract.Requires(offset >= 0);
      Contract.Requires(blocksAlreadyVisited != null);

      blocksAlreadyVisited.Add(bb);
      for (int i = offset, n = bb.Instructions.Count; i < n; i++) {
        var instruction = bb.Instructions[i];
        switch (instruction.Operation.OperationCode) {
          case OperationCode.Ldloc:
          case OperationCode.Ldloc_0:
          case OperationCode.Ldloc_1:
          case OperationCode.Ldloc_2:
          case OperationCode.Ldloc_3:
          case OperationCode.Ldloc_S:
          case OperationCode.Ldloca:
          case OperationCode.Ldloca_S:
            if (instruction.Operation.Value == local) return false;
            break;

          case OperationCode.Stloc:
          case OperationCode.Stloc_0:
          case OperationCode.Stloc_1:
          case OperationCode.Stloc_2:
          case OperationCode.Stloc_3:
          case OperationCode.Stloc_S:
            if (instruction.Operation.Value == local) return true;
            break;
        }
      }
      var result = true;
      foreach (var successor in this.cdfg.SuccessorsFor(bb)) {
        Contract.Assume(successor != null);
        if (blocksAlreadyVisited.Contains(successor)) continue;
        result &= this.NextReferenceIsAssignment(local, successor, 0, blocksAlreadyVisited);
        if (!result) break;
      }
      return result;
    }
Ejemplo n.º 26
0
 private void DecompileIfThenElseStatement(BasicBlock b, int i)
 {
     List<IStatement> statements = b.Statements;
       ConditionalStatement/*?*/ conditionalStatement = statements[i++] as ConditionalStatement;
       if (conditionalStatement == null) return;
       IExpression condition;
       var trueBranch = UnwrapSingletonBlock(conditionalStatement.TrueBranch);
       GotoStatement/*?*/ gotoAfterThen = trueBranch as GotoStatement;
       if (gotoAfterThen == null) {
     gotoAfterThen = UnwrapSingletonBlock(conditionalStatement.FalseBranch) as GotoStatement;
     if (gotoAfterThen == null || !(trueBranch is EmptyStatement)) return;
     condition = conditionalStatement.Condition;
       } else {
     if (!(conditionalStatement.FalseBranch is EmptyStatement)) return;
     LogicalNot not = new LogicalNot();
     not.Operand = conditionalStatement.Condition;
     condition = not;
       }
       //At this point we have:
       //if (!condition) goto afterThen;
       var afterThen = this.FindLabeledStatement(statements, i, gotoAfterThen.TargetStatement.Label);
       if (afterThen == null) return;
       List<IGotoStatement> branchesToThisLabel;
       if (this.predecessors.TryGetValue(afterThen, out branchesToThisLabel))
     branchesToThisLabel.Remove(gotoAfterThen);
       BasicBlock ifBlock = this.ExtractBasicBlockUpto(b, i, afterThen);
       GotoStatement/*?*/ gotoEndif = this.RemoveAndReturnLastGotoStatement(ifBlock);
       this.Traverse(ifBlock);
       BasicBlock elseBlock = null;
       if (gotoEndif != null) {
     var endif = this.FindLabeledStatement(statements, i, gotoEndif.TargetStatement.Label);
     if (endif != null) {
       if (this.predecessors.TryGetValue(gotoEndif.TargetStatement, out branchesToThisLabel))
     branchesToThisLabel.Remove(gotoEndif);
       elseBlock = this.ExtractBasicBlockUpto(b, i, gotoEndif.TargetStatement);
       elseBlock.Statements.Add(gotoEndif.TargetStatement);
       this.Traverse(elseBlock);
       elseBlock.Statements.Remove(gotoEndif.TargetStatement);
     } else {
       ifBlock.Statements.Add(gotoEndif);
     }
       }
       conditionalStatement.Condition = condition;
       conditionalStatement.TrueBranch = ifBlock;
       if (elseBlock != null)
     conditionalStatement.FalseBranch = elseBlock;
       else
     conditionalStatement.FalseBranch = new EmptyStatement();
       return;
 }
Ejemplo n.º 27
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="offset"></param>
 /// <param name="addLabel"></param>
 /// <returns></returns>
 protected BasicBlock GetOrCreateBlock(uint offset, bool addLabel)
 {
     BasicBlock result;
       if (!this.blockFor.TryGetValue(offset, out result)) {
     result = new BasicBlock(offset);
     this.blockFor.Add(offset, result);
       }
       if (addLabel && result.Statements.Count == 0) {
     LabeledStatement label = new LabeledStatement();
     label.Label = this.nameTable.GetNameFor("IL_" + offset.ToString("x4"));
     label.Statement = new EmptyStatement();
     result.Statements.Add(label);
     this.targetStatementFor.Add(offset, label);
       }
       return result;
 }
Ejemplo n.º 28
0
 internal static uint GetStartOffset(BasicBlock <Instruction> basicBlock)
 {
     Contract.Assume(basicBlock != null);
     Contract.Assume(basicBlock.Instructions.Count > 0);
     return(basicBlock.Instructions[0].Operation.Offset);
 }
Ejemplo n.º 29
0
 /// <summary>
 /// Perform different phases approppriate for normal, MoveNext, or iterator source method bodies.
 /// </summary>
 /// <param name="rootBlock"></param>
 /// <returns></returns>
 protected IBlockStatement Transform(BasicBlock rootBlock)
 {
     new TypeInferencer((INamedTypeDefinition)this.ilMethodBody.MethodDefinition.ContainingType, this.host).Traverse(rootBlock);
       new PatternDecompiler(this, this.predecessors).Traverse(rootBlock);
       new RemoveBranchConditionLocals(this).Traverse(rootBlock);
       new Unstacker(this).Visit(rootBlock);
       new TypeInferencer((INamedTypeDefinition)this.ilMethodBody.MethodDefinition.ContainingType, this.host).Traverse(rootBlock);
       new TryCatchDecompiler(this.host.PlatformType, this.predecessors).Traverse(rootBlock);
       new IfThenElseDecompiler(this.host.PlatformType, this.predecessors).Traverse(rootBlock);
       new SwitchDecompiler(this.host.PlatformType, this.predecessors).Traverse(rootBlock);
       if ((this.options & DecompilerOptions.Loops) != 0) {
     new WhileLoopDecompiler(this.host.PlatformType, this.predecessors).Traverse(rootBlock);
     new ForLoopDecompiler(this.host.PlatformType, this.predecessors).Traverse(rootBlock);
       }
       new BlockRemover().Traverse(rootBlock);
       new DeclarationAdder().Traverse(this, rootBlock);
       new EmptyStatementRemover().Traverse(rootBlock);
       IBlockStatement result = rootBlock;
       if ((this.options & DecompilerOptions.Iterators) != 0) {
     IMethodBody moveNextILBody = this.FindClosureMoveNext(rootBlock);
     if (moveNextILBody != Dummy.MethodBody) {
       if (this.privateHelperTypesToRemove == null) this.privateHelperTypesToRemove = new List<ITypeDefinition>(1);
       this.privateHelperTypesToRemove.Add(moveNextILBody.MethodDefinition.ContainingTypeDefinition);
       var moveNextBody = new MoveNextSourceMethodBody(this.ilMethodBody, moveNextILBody, this.host, this.sourceLocationProvider, this.localScopeProvider, this.options);
       result = moveNextBody.TransformedBlock;
     }
       }
       result = new CompilationArtifactRemover(this, (this.options & DecompilerOptions.AnonymousDelegates) != 0).RemoveCompilationArtifacts((BlockStatement)result);
       var bb = result as BasicBlock;
       if (bb != null) {
     new UnreferencedLabelRemover(this).Traverse(bb);
     new TypeInferencer((INamedTypeDefinition)this.ilMethodBody.MethodDefinition.ContainingType, this.host).Traverse(bb);
       }
       return result;
 }
Ejemplo n.º 30
0
 private static ILocalDefinition ExtractExceptionContainer(BasicBlock bb)
 {
     ILocalDefinition result = Dummy.LocalVariable;
       if (bb.Statements.Count < 1) return result;
       ExpressionStatement es = bb.Statements[0] as ExpressionStatement;
       if (es == null) return result;
       if (es.Expression is Pop) {
     bb.Statements.RemoveAt(0);
     return result;
       }
       Assignment assign = es.Expression as Assignment;
       if (assign == null) return result;
       if (!(assign.Source is Pop)) return result;
       if (!(assign.Target.Definition is ILocalDefinition)) return result;
       result = (ILocalDefinition)assign.Target.Definition;
       bb.Statements.RemoveAt(0);
       if (bb.LocalVariables != null && bb.LocalVariables.Remove(result))
     return result;
       if (bb.Statements.Count > 0) {
     BasicBlock nbb = bb.Statements[0] as BasicBlock;
     if (nbb != null && nbb.LocalVariables != null)
       nbb.LocalVariables.Remove(result);
       }
       return result;
 }
Ejemplo n.º 31
0
 // For the first assignment to a local variable in a block before a control statement is hit,
 // if the local variable is not mentioned previously, we turn this assignment into a local declaration.
 private void AddDeclarationsWithInitialValues(IEnumerable<ILocalDefinition> localVariables, BasicBlock block)
 {
     List<ILocalDefinition> topLevelLocals = new List<ILocalDefinition>(localVariables);
       List<ILocalDefinition> localsMet = new List<ILocalDefinition>();
       for (int i = 0; i < block.Statements.Count; i++) {
     if (topLevelLocals.Count == 0) break;
     IExpressionStatement expressionStatement = block.Statements[i] as IExpressionStatement;
     if (expressionStatement != null) {
       IAssignment assignment = expressionStatement.Expression as IAssignment;
       if (assignment != null) {
     ILocalDefinition localDef = assignment.Target.Definition as ILocalDefinition;
     if (localDef != null && topLevelLocals.Contains(localDef) && !localsMet.Contains(localDef) && !this.declaredLocals.ContainsKey(localDef)) {
       LocalDeclarationStatement localDecl = new LocalDeclarationStatement() {
         LocalVariable = localDef, InitialValue = assignment.Source, Locations = new List<ILocation>(expressionStatement.Locations),
       };
       this.declaredLocals.Add(localDef, true);
       block.Statements[i] = localDecl;
       topLevelLocals.Remove(localDef);
       localsMet.Add(localDef);
     }
       }
     }
     LocalFinder finder = new LocalFinder();
     finder.Traverse(block.Statements[i]);
     foreach (ILocalDefinition local in finder.FoundLocals) {
       if (!localsMet.Contains(local)) localsMet.Add(local);
     }
     //Once we see a statement that can transfer control somewhere else, we
     //no longer know that any subsequent assignment dominates all references
     //and hence cannot postpone adding the declaration until we can unify it with the assignment.
     IGotoStatement gotoStatement = block.Statements[i] as IGotoStatement;
     if (gotoStatement != null) break;
     IConditionalStatement conditionalStatement = block.Statements[i] as IConditionalStatement;
     if (conditionalStatement != null) break;
     ISwitchStatement switchStatement = block.Statements[i] as ISwitchStatement;
     if (switchStatement != null) break;
     IForEachStatement foreachStatement = block.Statements[i] as IForEachStatement;
     if (foreachStatement != null) break;
     IForStatement forStatement = block.Statements[i] as IForStatement;
     if (forStatement != null) break;
     ITryCatchFinallyStatement tryStatement = block.Statements[i] as ITryCatchFinallyStatement;
     if (tryStatement != null) break;
       }
 }
Ejemplo n.º 32
0
 protected override void Traverse(BasicBlock b)
 {
     for (int i = 0; i < b.Statements.Count; i++) {
     this.DecompileIfThenElseStatement(b, i);
       }
 }