Exemple #1
0
 /// <summary>
 /// Transform local exception variable.
 /// </summary>
 void TransformCatchVariable(TryCatchHandler handler, Block entryPoint)
 {
     if (!entryPoint.Instructions[0].MatchStLoc(out var exceptionVar, out var exceptionSlotLoad))
     {
         return;
     }
     if (!exceptionVar.IsSingleDefinition || exceptionVar.Kind != VariableKind.Local)
     {
         return;
     }
     if (!exceptionSlotLoad.MatchLdLoc(handler.Variable) || !handler.Variable.IsSingleDefinition || handler.Variable.LoadCount != 1)
     {
         return;
     }
     handler.Variable  = exceptionVar;
     exceptionVar.Kind = VariableKind.Exception;
     entryPoint.Instructions.RemoveAt(0);
 }
        /// <summary>
        /// catch ex : TException when (...) BlockContainer {
        ///     Block entryPoint (incoming: 1) {
        ///         stloc v(ldloc ex)
        ///         ...
        ///     }
        /// }
        /// =>
        /// catch v : TException when (...) BlockContainer {
        ///     Block entryPoint (incoming: 1) {
        ///         ...
        ///     }
        /// }
        /// </summary>
        void TransformCatchVariable(TryCatchHandler handler, Block entryPoint, bool isCatchBlock)
        {
            if (!handler.Variable.IsSingleDefinition || handler.Variable.LoadCount != 1)
            {
                return;                 // handle.Variable already has non-trivial uses
            }
            if (!entryPoint.Instructions[0].MatchStLoc(out var exceptionVar, out var exceptionSlotLoad))
            {
                // Not the pattern with a second exceptionVar.
                // However, it is still possible that we need to remove a pointless UnboxAny:
                if (handler.Variable.LoadInstructions.Single().Parent is UnboxAny inlinedUnboxAny)
                {
                    if (inlinedUnboxAny.Type.Equals(handler.Variable.Type))
                    {
                        context.Step("TransformCatchVariable - remove inlined UnboxAny", inlinedUnboxAny);
                        inlinedUnboxAny.ReplaceWith(inlinedUnboxAny.Argument);
                        foreach (var range in inlinedUnboxAny.ILRanges)
                        {
                            handler.AddExceptionSpecifierILRange(range);
                        }
                    }
                }
                return;
            }
            if (exceptionVar.Kind != VariableKind.Local && exceptionVar.Kind != VariableKind.StackSlot)
            {
                return;
            }
            if (exceptionSlotLoad is UnboxAny unboxAny)
            {
                // When catching a type parameter, csc emits an unbox.any instruction
                if (!unboxAny.Type.Equals(handler.Variable.Type))
                {
                    return;
                }
                exceptionSlotLoad = unboxAny.Argument;
            }
            if (!exceptionSlotLoad.MatchLdLoc(handler.Variable))
            {
                return;
            }
            // Check that exceptionVar is only used within the catch block:
            var allUses = exceptionVar.LoadInstructions
                          .Concat(exceptionVar.StoreInstructions.Cast <ILInstruction>())
                          .Concat(exceptionVar.AddressInstructions);

            foreach (var inst in allUses)
            {
                if (!inst.IsDescendantOf(handler))
                {
                    return;
                }
            }
            context.Step("TransformCatchVariable", entryPoint.Instructions[0]);
            exceptionVar.Kind = VariableKind.ExceptionLocal;
            exceptionVar.Type = handler.Variable.Type;
            handler.Variable  = exceptionVar;
            if (isCatchBlock)
            {
                foreach (var offset in entryPoint.Instructions[0].Descendants.SelectMany(o => o.ILRanges))
                {
                    handler.AddExceptionSpecifierILRange(offset);
                }
            }
            entryPoint.Instructions.RemoveAt(0);
        }
 protected override void BeginTryCatchHandler(TryCatchHandler inst)
 {
     HandleStore(inst.Variable);
     base.BeginTryCatchHandler(inst);
 }
Exemple #4
0
 /// <summary>
 /// TryCatchHandler is handled directly in VisitTryCatch
 /// </summary>
 protected internal override sealed void VisitTryCatchHandler(TryCatchHandler inst)
 {
     throw new NotSupportedException();
 }
Exemple #5
0
 protected virtual void BeginTryCatchHandler(TryCatchHandler inst)
 {
 }