示例#1
0
 /// <summary>
 ///	stloc lockObj(lockExpression)
 ///	call Enter(ldloc lockObj)
 ///	.try BlockContainer {
 ///		Block lockBlock (incoming: 1) {
 ///			call WriteLine()
 ///			leave lockBlock (nop)
 ///		}
 ///
 ///	} finally BlockContainer {
 ///		Block exitBlock (incoming: 1) {
 ///			call Exit(ldloc lockObj)
 ///			leave exitBlock (nop)
 ///		}
 ///
 ///	}
 /// =>
 /// .lock (lockExpression) BlockContainer {
 ///     Block lockBlock (incoming: 1) {
 ///			call WriteLine()
 ///			leave lockBlock (nop)
 ///		}
 /// }
 /// </summary>
 bool TransformLockMCS(Block block, int i)
 {
     if (i < 2)
     {
         return(false);
     }
     if (!(block.Instructions[i] is TryFinally body) || !(block.Instructions[i - 2] is StLoc objectStore) ||
         !MatchCall(block.Instructions[i - 1] as Call, "Enter", objectStore.Variable))
     {
         return(false);
     }
     if (!objectStore.Variable.IsSingleDefinition)
     {
         return(false);
     }
     if (!(body.TryBlock is BlockContainer tryContainer) || tryContainer.EntryPoint.Instructions.Count == 0 || tryContainer.EntryPoint.IncomingEdgeCount != 1)
     {
         return(false);
     }
     if (!(body.FinallyBlock is BlockContainer finallyContainer) || !MatchExitBlock(finallyContainer.EntryPoint, null, objectStore.Variable))
     {
         return(false);
     }
     if (objectStore.Variable.LoadCount > 2)
     {
         return(false);
     }
     context.Step("LockTransformMCS", block);
     block.Instructions.RemoveAt(i - 1);
     block.Instructions.RemoveAt(i - 2);
     body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock).WithILRange(objectStore));
     return(true);
 }
示例#2
0
 public void Run(Block block, BlockTransformContext context)
 {
     for (int i = 0; i < block.Instructions.Count; i++)
     {
         ILVariable    v;
         ILInstruction copiedExpr;
         if (block.Instructions[i].MatchStLoc(out v, out copiedExpr))
         {
             if (v.IsSingleDefinition && v.LoadCount == 0 && v.Kind == VariableKind.StackSlot)
             {
                 // dead store to stack
                 if (SemanticHelper.IsPure(copiedExpr.Flags))
                 {
                     // no-op -> delete
                     context.Step("remove dead store to stack: no-op -> delete", block.Instructions[i]);
                     block.Instructions.RemoveAt(i--);
                 }
                 else
                 {
                     // evaluate the value for its side-effects
                     context.Step("remove dead store to stack: evaluate the value for its side-effects", block.Instructions[i]);
                     copiedExpr.AddILRange(block.Instructions[i]);
                     block.Instructions[i] = copiedExpr;
                 }
             }
             else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr))
             {
                 DoPropagate(v, copiedExpr, block, ref i, context);
             }
         }
     }
 }
        /// <summary>
        /// if (comp(ldsfld CachedAnonMethodDelegate == ldnull)) {
        ///     stsfld CachedAnonMethodDelegate(DelegateConstruction)
        /// }
        /// ... one usage of CachedAnonMethodDelegate ...
        /// =>
        /// ... one usage of DelegateConstruction ...
        /// </summary>
        bool CachedDelegateInitializationWithField(IfInstruction inst)
        {
            Block trueInst = inst.TrueInst as Block;

            if (trueInst == null || trueInst.Instructions.Count != 1 || !inst.FalseInst.MatchNop())
            {
                return(false);
            }
            var storeInst = trueInst.Instructions[0];

            if (!inst.Condition.MatchCompEquals(out ILInstruction left, out ILInstruction right) || !left.MatchLdsFld(out IField field) || !right.MatchLdNull())
            {
                return(false);
            }
            if (!storeInst.MatchStsFld(out IField field2, out ILInstruction value) || !field.Equals(field2) || !field.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
            {
                return(false);
            }
            if (!DelegateConstruction.IsDelegateConstruction(value as NewObj, true))
            {
                return(false);
            }
            var nextInstruction = inst.Parent.Children.ElementAtOrDefault(inst.ChildIndex + 1);

            if (nextInstruction == null)
            {
                return(false);
            }
            var usages = nextInstruction.Descendants.Where(i => i.MatchLdsFld(field)).ToArray();

            if (usages.Length != 1)
            {
                return(false);
            }
            context.Step("CachedDelegateInitializationWithField", inst);
            usages[0].ReplaceWith(value);
            return(true);
        }
示例#4
0
 /// <summary>
 /// stloc obj(resourceExpression)
 /// .try BlockContainer {
 ///		Block IL_0003(incoming: 1) {
 ///			call WriteLine(ldstr "using (null)")
 ///			leave IL_0003(nop)
 ///		}
 ///	} finally BlockContainer {
 ///		Block IL_0012(incoming: 1) {
 ///			if (comp(ldloc obj != ldnull)) Block IL_001a  {
 ///				callvirt Dispose(ldnull)
 ///			}
 ///			leave IL_0012(nop)
 ///		}
 /// }
 /// leave IL_0000(nop)
 /// =>
 /// using (resourceExpression) {
 ///		BlockContainer {
 ///			Block IL_0003(incoming: 1) {
 ///				call WriteLine(ldstr "using (null)")
 ///				leave IL_0003(nop)
 ///			}
 ///		}
 /// }
 /// </summary>
 bool TransformUsing(Block block, int i)
 {
     if (i < 1)
     {
         return(false);
     }
     if (!(block.Instructions[i] is TryFinally tryFinally) || !(block.Instructions[i - 1] is StLoc storeInst))
     {
         return(false);
     }
     if (!(storeInst.Value.MatchLdNull() || CheckResourceType(storeInst.Variable.Type)))
     {
         return(false);
     }
     if (storeInst.Variable.LoadInstructions.Any(ld => !ld.IsDescendantOf(tryFinally)))
     {
         return(false);
     }
     if (storeInst.Variable.AddressInstructions.Any(la => !la.IsDescendantOf(tryFinally) || (la.IsDescendantOf(tryFinally.TryBlock) && !ILInlining.IsUsedAsThisPointerInCall(la))))
     {
         return(false);
     }
     if (storeInst.Variable.StoreInstructions.Count > 1)
     {
         return(false);
     }
     if (!(tryFinally.FinallyBlock is BlockContainer container) || !MatchDisposeBlock(container, storeInst.Variable, storeInst.Value.MatchLdNull()))
     {
         return(false);
     }
     context.Step("UsingTransform", tryFinally);
     storeInst.Variable.Kind = VariableKind.UsingLocal;
     block.Instructions.RemoveAt(i);
     block.Instructions[i - 1] = new UsingInstruction(storeInst.Variable, storeInst.Value, tryFinally.TryBlock).WithILRange(storeInst);
     return(true);
 }
示例#5
0
 public void Run(Block block, BlockTransformContext context)
 {
     if (running)
     {
         throw new InvalidOperationException("LoopingBlockTransform already running. Transforms (and the CSharpDecompiler) are neither thread-safe nor re-entrant.");
     }
     running = true;
     try {
         int count = 1;
         do
         {
             block.ResetDirty();
             block.RunTransforms(children, context);
             if (block.IsDirty)
             {
                 context.Step($"Block is dirty; running loop iteration #{++count}.", block);
             }
         } while (block.IsDirty);
     } finally {
         running = false;
     }
 }