Example #1
0
        public override Expression GenDlr(GenContext context)
        {
            Expression basicBody = _tryExpr.GenDlr(context);
            // Wrap the basic body, a Comma, in a return to a label
            //LabelTarget target = Expression.Label(basicBody.Type, "ret_label");
            //Expression tryBody = Expression.Return(target, basicBody);
            Expression tryBody = Expression.Convert(basicBody,typeof(object));

            CatchBlock[] catches = new CatchBlock[_catchExprs.count()];
            for ( int i=0; i<_catchExprs.count(); i++ )
            {
                CatchClause clause = (CatchClause) _catchExprs.nth(i);
                ParameterExpression parmExpr = Expression.Parameter(clause.Type, clause.Lb.Name);
                clause.Lb.ParamExpression = parmExpr;
                catches[i] = Expression.Catch(parmExpr, Expression.Convert(clause.Handler.GenDlr(context), typeof(object)));
            }

            TryExpression tryStmt = _finallyExpr == null
                ? Expression.TryCatch(tryBody, catches)
                : Expression.TryCatchFinally(tryBody, _finallyExpr.GenDlr(context), catches);

            //Expression defaultValue = Expression.Default(basicBody.Type);
            //Expression whole = Expression.Block(tryStmt, Expression.Label(target, defaultValue));
            //return whole;
            return tryStmt;
        }
Example #2
0
        public override void VisitCFGCatchBlock(CatchBlock x)
        {
            VisitCFGBlockInit(x);

            // add catch control variable to the state
            Accept(x.Variable);
            VisitTypeRef(x.TypeRef);
            State.SetLocalType(State.GetLocalHandle(x.Variable.Name.NameValue.Value), TypeCtx.GetTypeMask(x.TypeRef.TypeRef));

            //
            x.Variable.ResultType = x.TypeRef.ResolvedType;

            //
            VisitCFGBlockInternal(x);
        }
        protected override CatchBlock VisitCatchBlock(CatchBlock node)
        {
            CompilerScope scope;

            if (node.Variable == null)
            {
                this.Visit(node.Body);
                return(node);
            }
            this._tree.Scopes[node] = scope = new CompilerScope(node, false);
            this._scopes.Push(scope);
            this.Visit(node.Body);
            this._scopes.Pop();
            return(node);
        }
Example #4
0
        public void SettingValues()
        {
            var sut = new CatchBlock
            {
                Kind      = CatchBlockKind.General,
                Parameter = SomeParameter(),
                Body      =
                {
                    new ReturnStatement()
                }
            };

            Assert.AreEqual(SomeParameter(), sut.Parameter);
            Assert.AreEqual(Lists.NewList(new ReturnStatement()), sut.Body);
            Assert.AreEqual(CatchBlockKind.General, sut.Kind);
        }
Example #5
0
        protected virtual bool CompareCatchBlock(CatchBlock node1, CatchBlock node2, object state)
        {
            if (AreBothNull(node1, node2))
            {
                return(true);
            }
            if (AreEitherNull(node1, node2))
            {
                return(false);
            }

            return(CompareType(node1.Test, node2.Test, state) &&
                   Compare(node1.Body, node2.Body, state) &&
                   CompareParameter(node1.Variable, node2.Variable, state) &&
                   Compare(node1.Filter, node2.Filter, state));
        }
        /// <inheritdoc/>
        protected override CatchBlock VisitCatchBlock(CatchBlock node)
        {
            Debug.Assert(node != null);
            var expected = PeekExpectedExpressionNode <CatchBlock>();

            if (!CheckNotNull(expected))
            {
                return(node);
            }
            if (!CheckEqual(node.Test, expected.Test))
            {
                return(node);
            }
            PopExpectedExpressionNode();
            return(base.VisitCatchBlock(node));
        }
 protected void VisitCatchBlock(CatchBlock node, TState variableState, TState filterState, TState bodyState, bool visitVariable, bool visitFilter, bool visitBody)
 {
     ValidateArguments(node);
     if (visitVariable && node.Variable != null)
     {
         Visit(Context.Create(node, variableState), node.Variable);
     }
     if (visitFilter && node.Filter != null)
     {
         Visit(Context.Create(node, filterState), node.Filter);
     }
     if (visitBody && node.Body != null)
     {
         Visit(Context.Create(node, bodyState), node.Body);
     }
 }
Example #8
0
            protected override CatchBlock VisitCatchBlock(CatchBlock node)
            {
                if (node.Variable != null)
                {
                    PushParameters(new[] { node.Variable });
                }

                Visit(node.Body);
                Visit(node.Filter);
                if (node.Variable != null)
                {
                    PopParameters(new[] { node.Variable });
                }

                return(node);
            }
Example #9
0
        protected virtual bool CompareCatchBlock(CatchBlock a, CatchBlock b)
        {
            if (a.Variable != null && b.Variable != null)
            {
                if (a.Variable.Type != b.Variable.Type)
                {
                    return(false);
                }
                this.parameterScope.Add(a.Variable, b.Variable);
            }

            return(a.Test == b.Test &&
                   this.Compare(a.Body, b.Body) &&
                   this.Compare(a.Filter, b.Filter) &&
                   this.Compare(a.Variable, b.Variable));
        }
Example #10
0
        private static string GetCatchBlock(CatchBlock catchBlock, TranslationContext context)
        {
            var catchBody = context.TranslateCodeBlock(catchBlock.Body);

            var exceptionClause = GetExceptionClause(catchBlock, context);

            var catchBodyBlock = catchBody.WithCurlyBraces();

            if (catchBlock.Variable != null)
            {
                catchBodyBlock = catchBodyBlock
                                 .Replace($"throw {catchBlock.Variable.Name};", "throw;");
            }

            return($@"catch{exceptionClause}{catchBodyBlock}
");
        }
Example #11
0
        protected override CatchBlock VisitCatchBlock(CatchBlock node)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            var vistedNode = base.VisitCatchBlock(node);

            // Testing the parent expression is only required if all children are evaluatable
            if (IsCurrentSubtreeEvaluatable)
            {
                IsCurrentSubtreeEvaluatable = EvaluatableExpressionFilter.IsEvaluatableCatchBlock(node);
            }

            return(vistedNode);
        }
Example #12
0
        private static string GetExceptionClause(CatchBlock catchBlock, TranslationContext context)
        {
            var exceptionTypeName = catchBlock.Test.GetFriendlyName();

            if (ExceptionUsageFinder.IsVariableUsed(catchBlock))
            {
                var filter = (catchBlock.Filter != null)
                    ? " when " + context.Translate(catchBlock.Filter)
                    : null;

                return($" ({exceptionTypeName} {catchBlock.Variable.Name})" + filter);
            }

            return((catchBlock.Test != typeof(Exception))
                ? $" ({exceptionTypeName})"
                : null);
        }
Example #13
0
        public override void VisitCFGCatchBlock(CatchBlock x)
        {
            VisitCFGBlockInit(x);

            // add catch control variable to the state
            x.TypeRef.Accept(this);
            x.Variable.Access = BoundAccess.Write.WithWrite(TypeCtx.GetTypeMask(x.TypeRef.TypeRef));
            State.SetLocalType(State.GetLocalHandle(x.Variable.Name.NameValue), x.Variable.Access.WriteMask);

            Accept(x.Variable);

            //
            x.Variable.ResultType = x.TypeRef.ResolvedType;

            //
            VisitCFGBlockInternal(x);
        }
        static void Main(string[] args)
        {
            Loader.Load();
            Objects.LoadType(typeof(DynamicLinqTestObjects));

            var lines = new List <string>();

            foreach (var(key, filename) in rendererFileMapping.SelectKVP((k, v) => (k, v)))
            {
                var ordering = parseFileOrder(@$ "C:\Users\Spitz\source\repos\zspitz\ExpressionTreeToString\Tests\expectedResults\{filename}-testdata.txt");

                var language = key == VisualBasic ? Language.VisualBasic : Language.CSharp;

                const string dlinq   = nameof(DynamicLinqTestObjects);
                var          objects = Objects.Get()
                                       .Where(x => key == DynamicLinq ? x.source == dlinq : x.source != dlinq)
                                       .Where(x => !ordering.ContainsKey($"{x.source}.{x.name}"));

                //var objects = Objects.Get()
                //    .Where(x => key == DynamicLinq ? x.source == dlinq : x.source != dlinq)
                //    .OrderBy(x => ordering.TryGetValue($"{x.source}.{x.name}", out var order) ? order : -1);

                foreach (var(category, source, name, o) in objects)
                {
                    var toWrite = o switch
                    {
                        Expression expr => expr.ToString(key, out var pathSpans, language),
                        MemberBinding mbind => mbind.ToString(key, out var pathSpans, language),
                        ElementInit init => init.ToString(key, out var pathSpans, language),
                        SwitchCase switchCase => switchCase.ToString(key, out var pathSpans, language),
                        CatchBlock catchBlock => catchBlock.ToString(key, out var pathSpans, language),
                        LabelTarget labelTarget => labelTarget.ToString(key, out var pathSpans, language),
                        _ => throw new NotImplementedException(),
                    };
                    lines.Add($"---- {source}.{name}");
                    if (key == FactoryMethods)
                    {
                        toWrite = toWrite.Replace(@"// using static System.Linq.Expressions.Expression

", "");
                    }
                    lines.Add(toWrite);
                }

                lines.Add("------");
            }
Example #15
0
 protected override CatchBlock VisitCatchBlock(CatchBlock node, Type expectedType)
 {
     if (evaluator.EnsureKnownType(
             node.Test,
             genericArgumentsUpdated: updatedType => node = Expression.MakeCatchBlock(
                 updatedType,
                 VisitAndConvert(node.Variable, "VisitCatchBlock-Variable", null),
                 Visit(node.Body, expectedType),
                 Visit(node.Filter, typeof(bool)))))
     {
         return(node);
     }
     else
     {
         return(base.VisitCatchBlock(node, expectedType));
     }
 }
Example #16
0
            protected override CatchBlock VisitCatchBlock(CatchBlock node)
            {
                if (node.Filter != null)
                {
                    Visit(node.Body);

                    _forbidden.Push(nameof(CatchBlock));
                    {
                        Visit(node.Filter);
                    }
                    _forbidden.Pop();

                    return(node);
                }

                return(base.VisitCatchBlock(node));
            }
            public CatchBlockTranslation(CatchBlock catchBlock, ITranslationContext context)
            {
                _catchBodyTranslation = GetBlockTranslation(catchBlock.Body, context);
                _exceptionClause      = GetExceptionClauseOrNullFor(catchBlock, context);

                if ((_catchBodyTranslation.NodeType != ExpressionType.Throw) && catchBlock.Body.IsReturnable())
                {
                    _catchBodyTranslation.WithReturnKeyword();
                }

                EstimatedSize = _catchBodyTranslation.EstimatedSize;

                if (_exceptionClause != null)
                {
                    EstimatedSize += _exceptionClause.EstimatedSize;
                }
            }
Example #18
0
        private int DoAppendCatchString(StringBuilder builder, CatchBlock block, int indent)
        {
            builder.Append(' ', 3 * indent);
            builder.Append("catch ");
            builder.Append(block.CatchType.ToString());
            builder.Append(Environment.NewLine);
            ++indent;

            int index = block.Index;

            while (index < block.Index + block.Length)
            {
                index += DoAppendInstructionString(builder, index, indent);
            }
            --indent;

            return(block.Length);
        }
Example #19
0
        protected override CatchBlock VisitCatchBlock(CatchBlock node)
        {
            if (node.Variable == null)
            {
                Visit(node.Filter);
                Visit(node.Body);
                return(node);
            }

            var createdScope = new CompilerScope(node, false);

            _tree.Scopes[node] = createdScope;
            _scopes.Push(createdScope);
            Visit(node.Filter);
            Visit(node.Body);
            _scopes.Pop();
            return(node);
        }
        private CatchBlockDto GetCatchBlock(CatchBlock obj)
        {
            if (this.catchBlocks.ContainsKey(obj))
            {
                return(this.catchBlocks[obj]);
            }

            var res = new CatchBlockDto
            {
                Body     = Visit(obj.Body),
                Filter   = Visit(obj.Filter),
                Test     = obj.Test,
                Variable = Visit((Expression)obj.Variable) as ParameterExpressionDto
            };

            this.catchBlocks.Add(obj, res);
            return(res);
        }
                public static bool IsVariableUsed(CatchBlock catchHandler)
                {
                    if (catchHandler.Variable == null)
                    {
                        return(false);
                    }

                    var visitor = new ExceptionUsageFinder(catchHandler);

                    visitor.Visit(catchHandler.Filter);

                    if (!visitor._usageFound)
                    {
                        visitor.Visit(catchHandler.Body);
                    }

                    return(visitor._usageFound);
                }
Example #22
0
        public override void VisitTryStatement(ITryStatement block, IList <IStatement> body)
        {
            AddIf(block, CompletionCase.EmptyCompletionBefore, body);

            var tryBlock = new TryBlock();

            body.Add(tryBlock);

            AddIf(block, CompletionCase.InBody, tryBlock.Body);
            AddIf(block, CompletionCase.InFinally, tryBlock.Finally);
            VisitBlock(block.Try, tryBlock.Body);
            VisitBlock(block.FinallyBlock, tryBlock.Finally);

            foreach (var clause in block.Catches)
            {
                var catchBlock = new CatchBlock();
                tryBlock.CatchBlocks.Add(catchBlock);

                AddIf(clause, CompletionCase.InBody, catchBlock.Body);

                VisitBlock(clause.Body, catchBlock.Body);

                var generalClause = clause as IGeneralCatchClause;
                if (generalClause != null)
                {
                    catchBlock.Kind = CatchBlockKind.General;
                    continue;
                }

                var specificClause = clause as ISpecificCatchClause;
                if (specificClause != null)
                {
                    var varDecl   = specificClause.ExceptionDeclaration;
                    var isUnnamed = varDecl == null;

                    var typeName = specificClause.ExceptionType.GetName();
                    var varName  = isUnnamed ? "?" : varDecl.DeclaredName;
                    catchBlock.Parameter = Names.Parameter("[{0}] {1}", typeName, varName);
                    catchBlock.Kind      = isUnnamed ? CatchBlockKind.Unnamed : CatchBlockKind.Default;
                }
            }

            AddIf(block, CompletionCase.EmptyCompletionAfter, body);
        }
        protected override CatchBlock VisitCatchBlock(CatchBlock node)
        {
            if (node.Variable != null)
            {
                this._shadowedVars.Push(new HashSet <ParameterExpression>(new ParameterExpression[] { node.Variable }));
            }
            Expression body   = this.Visit(node.Body);
            Expression filter = this.Visit(node.Filter);

            if (node.Variable != null)
            {
                this._shadowedVars.Pop();
            }
            if ((body == node.Body) && (filter == node.Filter))
            {
                return(node);
            }
            return(Expression.MakeCatchBlock(node.Test, node.Variable, body, filter));
        }
Example #24
0
 protected override CatchBlock VisitCatchBlock(CatchBlock node)
 {
     Out(Flow.NewLine, "} .Catch (" + node.Test.ToString());
     if (node.Variable != null)
     {
         Out(Flow.Space, "");
         VisitParameter(node.Variable);
     }
     if (node.Filter != null)
     {
         Out(") .If (", Flow.Break);
         Visit(node.Filter);
     }
     Out(") {", Flow.NewLine);
     Indent();
     Visit(node.Body);
     Dedent();
     return(node);
 }
            protected override CatchBlock VisitCatchBlock(CatchBlock node)
            {
                if (node.Variable != null)
                {
                    _shadowedVars.Push(new Set <ParameterExpression>(new[] { node.Variable }));
                }
                Expression b = Visit(node.Body);
                Expression f = Visit(node.Filter);

                if (node.Variable != null)
                {
                    _shadowedVars.Pop();
                }
                if (b == node.Body && f == node.Filter)
                {
                    return(node);
                }
                return(Expression.MakeCatchBlock(node.Test, node.Variable, b, f));
            }
Example #26
0
            private TryExpression DeserializeTry()
            {
                var flags = _stream.ReadByte();

                var type = default(Type);

                if ((flags & Protocol.TRY_HASTYPE) == Protocol.TRY_HASTYPE)
                {
                    type = DeserializeType();
                }

                var body = Deserialize();

                var handlers = default(CatchBlock[]);

                if ((flags & Protocol.TRY_HASCATCH) == Protocol.TRY_HASCATCH)
                {
                    var n = (int)_stream.ReadUInt32Compact();

                    handlers = new CatchBlock[n];

                    for (var i = 0; i < n; i++)
                    {
                        handlers[i] = DeserializeCatchBlock();
                    }
                }

                var fault = default(Expression);

                if ((flags & Protocol.TRY_HASFAULT) == Protocol.TRY_HASFAULT)
                {
                    fault = Deserialize();
                }

                var @finally = default(Expression);

                if ((flags & Protocol.TRY_HASFINALLY) == Protocol.TRY_HASFINALLY)
                {
                    @finally = Deserialize();
                }

                return(_parent._factory.MakeTry(type, body, @finally, fault, handlers));
            }
        static ManagedWrapper()
        {
            // Create sub-expressions which don't depend on the interface type. This saves a bit of resources.
            paramNativeObject = Expression.Parameter(typeof(IntPtr), "pNative");

            Type       tException         = typeof(Exception);
            MethodInfo miExceptionHresult = tException.GetProperty("HResult").GetGetMethod();

            // Create return target and catch block, they don't depend on the interface nor the input object
            returnTarget = Expression.Label(typeof(int));
            var eException = Expression.Parameter(typeof(Exception), "ex");
            var eCatchBody = Expression.Return(returnTarget, Expression.Property(eException, miExceptionHresult));

            exprCatchBlock = Expression.Catch(eException, eCatchBody);

            // Same for pointer-returning methods
            pointerReturnTarget   = Expression.Label(typeof(IntPtr));
            eCatchBody            = Expression.Return(pointerReturnTarget, MiscUtils.nullptr);
            exprPointerCatchBlock = Expression.Catch(eException, eCatchBody);
        }
        /// <summary>
        /// Returns an enumerator that iterates through the CatchBlock.
        /// </summary>
        /// <param name="catchBlock">The CatchBlock to iterate.</param>
        /// <returns>An enumerator that can be used to iterate through the CatchBlock.</returns>
        /// <exception cref="ArgumentNullException">The CatchBlock is null.</exception>
        protected virtual IEnumerable <Expression> CatchBlockIterator([DisallowNull] CatchBlock catchBlock)
        {
            if (catchBlock.Variable != null)
            {
                yield return(catchBlock.Variable);
            }

            if (catchBlock.Filter != null)
            {
                foreach (var filter in Iterator(catchBlock.Filter))
                {
                    yield return(filter);
                }
            }

            foreach (var body in Iterator(catchBlock.Body))
            {
                yield return(body);
            }
        }
Example #29
0
        private void HandleException(Node node, Exception exc)
        {
            // Searching appropriate handler
            Type    excType = exc.GetType();
            EHBlock handler = null;
            Block   parent  = node.Parent;

            while (!(parent is MethodBodyBlock))
            {
                if (parent is ProtectedBlock)
                {
                    ProtectedBlock tryBlock = parent as ProtectedBlock;

                    for (int count = 0; count < tryBlock.Count && handler == null; count++)
                    {
                        if (tryBlock[count] is CatchBlock)
                        {
                            CatchBlock catchBlock = tryBlock[count] as CatchBlock;

                            if (catchBlock.Type.IsAssignableFrom(excType))
                            {
                                handler = catchBlock;
                            }
                        }
                    }
                }

                parent = parent.Parent;
            }

            if (handler == null)
            {
                unhandledException = exc;
            }
            else
            {
                state.Stack.Clear();
                state.Stack.Push(new ObjectReferenceValue(exc));
                AddTask(handler);
            }
        }
        private void EmitCatchStart(CatchBlock cb)
        {
            if (cb.Filter == null)
            {
                EmitSaveExceptionOrPop(cb);
                return;
            }

            // emit filter block. Filter blocks are untyped so we need to do
            // the type check ourselves.
            var endFilter = IL.DefineLabel();
            var rightType = IL.DefineLabel();

            // skip if it's not our exception type, but save
            // the exception if it is so it's available to the
            // filter
            IL.Emit(OpCodes.Isinst, cb.Test);
            IL.Emit(OpCodes.Dup);
            IL.Emit(OpCodes.Brtrue, rightType);
            IL.Emit(OpCodes.Pop);
            IL.Emit(OpCodes.Ldc_I4_0);
            IL.Emit(OpCodes.Br, endFilter);

            // it's our type, save it and emit the filter.
            IL.MarkLabel(rightType);
            EmitSaveExceptionOrPop(cb);

            var parent = _labelBlock;

            _labelBlock = new LabelScopeInfo(parent, LabelScopeKind.Filter);

            EmitExpression(cb.Filter);

            _labelBlock = parent;

            // begin the catch, clear the exception, we've
            // already saved it
            IL.MarkLabel(endFilter);
            IL.BeginCatchBlock(null);
            IL.Emit(OpCodes.Pop);
        }
Example #31
0
        protected override CatchBlock VisitCatchBlock(CatchBlock node)
        {
            var peek     = localParameters.Peek();
            var variable = node.Variable;

            if (variable != null && peek.Contains(variable))
            {
                variable = null;
            }
            if (variable != null)
            {
                peek.Add(variable);
            }
            var res = base.VisitCatchBlock(node);

            if (variable != null)
            {
                peek.Remove(variable);
            }
            return(res);
        }
Example #32
0
        public Expression GenCode(RHC rhc, ObjExpr objx, GenContext context)
        {
            Expression basicBody = _tryExpr.GenCode(rhc, objx, context);
            if (basicBody.Type == typeof(void))
                basicBody = Expression.Block(basicBody, Expression.Default(typeof(object)));
            Expression tryBody = Expression.Convert(basicBody,typeof(object));

            CatchBlock[] catches = new CatchBlock[_catchExprs.count()];
            for ( int i=0; i<_catchExprs.count(); i++ )
            {
                CatchClause clause = (CatchClause) _catchExprs.nth(i);
                ParameterExpression parmExpr = Expression.Parameter(clause.Type, clause.Lb.Name);
                clause.Lb.ParamExpression = parmExpr;
                catches[i] = Expression.Catch(parmExpr, Expression.Convert(clause.Handler.GenCode(rhc, objx, context), typeof(object)));
            }

            TryExpression tryStmt = _finallyExpr == null
                ? Expression.TryCatch(tryBody, catches)
                : Expression.TryCatchFinally(tryBody, _finallyExpr.GenCode(RHC.Statement, objx, context), catches);

            return tryStmt;
        }
Example #33
0
		private int DoCheckCatch(TypedInstructionCollection instructions, CatchBlock cb, int varIndex)
		{
			int offset = -1;
			
			// Loop through all of the instructions in the catch block,
			for (int index = cb.Index; index < cb.Index + cb.Length && offset < 0; ++index)
			{
				TypedInstruction instruction = instructions[index];
				
				// if we find a throw instruction,
				if (instruction.Untyped.OpCode.Code == Code.Throw)
				{
					// and it's preceded by a load from varIndex then we have a problem.
					LoadLocal load = instructions[index - 1] as LoadLocal;
					if (load != null && load.Variable == varIndex)
					{
						offset = instruction.Untyped.Offset;
						Log.DebugLine(this, "bad throw at {0:X2}", offset); 
					}
				}
			}
			
			return offset;
		}
 protected internal virtual void PostWalk(CatchBlock node) { }
 // CatchBlock
 protected internal virtual bool Walk(CatchBlock node) { return true; }
        /// <summary>
        /// Emits the start of a catch block.  The exception value that is provided by the
        /// CLR is stored in the variable specified by the catch block or popped if no
        /// variable is provided.
        /// </summary>
        private void EmitCatchStart(CatchBlock cb) {
            if (cb.Filter != null && !IsDynamicMethod) {
                // emit filter block as filter.  Filter blocks are 
                // untyped so we need to do the type check ourselves.  
                _ilg.BeginExceptFilterBlock();

                Label endFilter = _ilg.DefineLabel();
                Label rightType = _ilg.DefineLabel();

                // skip if it's not our exception type, but save
                // the exception if it is so it's available to the
                // filter
                _ilg.Emit(OpCodes.Isinst, cb.Test);
                _ilg.Emit(OpCodes.Dup);
                _ilg.Emit(OpCodes.Brtrue, rightType);
                _ilg.Emit(OpCodes.Pop);
                _ilg.Emit(OpCodes.Ldc_I4_0);
                _ilg.Emit(OpCodes.Br, endFilter);

                // it's our type, save it and emit the filter.
                _ilg.MarkLabel(rightType);
                EmitSaveExceptionOrPop(cb);
                PushLabelBlock(LabelBlockKind.Filter);
                EmitExpression(cb.Filter);
                PopLabelBlock(LabelBlockKind.Filter);

                // begin the catch, clear the exception, we've 
                // already saved it
                _ilg.MarkLabel(endFilter);
                _ilg.BeginCatchBlock(null);
                _ilg.Emit(OpCodes.Pop);
            } else {
                _ilg.BeginCatchBlock(cb.Test);

                EmitSaveExceptionOrPop(cb);

                if (cb.Filter != null) {
                    Label catchBlock = _ilg.DefineLabel();

                    // filters aren't supported in dynamic methods so instead
                    // emit the filter as if check, if (!expr) rethrow
                    PushLabelBlock(LabelBlockKind.Filter);
                    EmitExpressionAndBranch(true, cb.Filter, catchBlock);
                    PopLabelBlock(LabelBlockKind.Filter);

                    _ilg.Emit(OpCodes.Rethrow);
                    _ilg.MarkLabel(catchBlock);

                    // catch body continues
                }
            }
        }
Example #37
0
 public virtual void VisitCFGCatchBlock(CatchBlock x)
 {
     Accept(x.Variable);
     VisitCFGBlockInternal(x);
 }
Example #38
0
        void EmitCatchBlock(CodeGenerator cg, CatchBlock catchBlock)
        {
            Debug.Assert(catchBlock.Variable.Variable != null);

            if (catchBlock.TypeRef.ResolvedType == null)
            {
                throw new NotImplementedException("handle exception type dynamically"); // TODO: if (ex is ctx.ResolveType(ExceptionTypeName)) { ... }
            }

            var extype = catchBlock.TypeRef.ResolvedType;

            cg.Builder.AdjustStack(1); // Account for exception on the stack.

            cg.Builder.OpenLocalScope(ScopeType.Catch, (Microsoft.Cci.ITypeReference)extype);

            // <tmp> = <ex>
            var tmploc = cg.GetTemporaryLocal(extype);
            cg.Builder.EmitLocalStore(tmploc);

            var varplace = catchBlock.Variable.BindPlace(cg);
            Debug.Assert(varplace != null);

            // $x = <tmp>
            varplace.EmitStorePrepare(cg);
            cg.Builder.EmitLocalLoad(tmploc);
            varplace.EmitStore(cg, (TypeSymbol)tmploc.Type);

            //
            cg.ReturnTemporaryLocal(tmploc);
            tmploc = null;

            //
            cg.GenerateScope(catchBlock, NextBlock.Ordinal);

            //
            cg.Builder.CloseLocalScope();
        }
Example #39
0
        public override void VisitCFGCatchBlock(CatchBlock x)
        {
            VisitCFGBlockInit(x);

            // add catch control variable to the state
            Accept(x.Variable);
            VisitTypeRef(x.TypeRef);

            //
            x.Variable.ResultType = x.TypeRef.ResolvedType;

            //
            VisitCFGBlockInternal(x);
        }
Example #40
0
 internal CatchRecord(LocalBuilder local, CatchBlock block) {
     _local = local;
     _block = block;
 }
 private void EmitSaveExceptionOrPop(CatchBlock cb) {
     if (cb.Variable != null) {
         // If the variable is present, store the exception
         // in the variable.
         _scope.EmitSet(cb.Variable);
     } else {
         // Otherwise, pop it off the stack.
         _ilg.Emit(OpCodes.Pop);
     }
 }
 public CatchBlockProxy(CatchBlock node) {
     _node = node;
 }
        /// <summary>
        /// Emits the start of a catch block.  The exception value that is provided by the
        /// CLR is stored in the variable specified by the catch block or popped if no
        /// variable is provided.
        /// </summary>
        private void EmitCatchStart(CatchBlock cb) {
            if (cb.Filter == null) {
                EmitSaveExceptionOrPop(cb);
                return;
            }

            // emit filter block. Filter blocks are untyped so we need to do
            // the type check ourselves.  
            Label endFilter = _ilg.DefineLabel();
            Label rightType = _ilg.DefineLabel();

            // skip if it's not our exception type, but save
            // the exception if it is so it's available to the
            // filter
            _ilg.Emit(OpCodes.Isinst, cb.Test);
            _ilg.Emit(OpCodes.Dup);
            _ilg.Emit(OpCodes.Brtrue, rightType);
            _ilg.Emit(OpCodes.Pop);
            _ilg.Emit(OpCodes.Ldc_I4_0);
            _ilg.Emit(OpCodes.Br, endFilter);

            // it's our type, save it and emit the filter.
            _ilg.MarkLabel(rightType);
            EmitSaveExceptionOrPop(cb);
            PushLabelBlock(LabelScopeKind.Filter);
            EmitExpression(cb.Filter);
            PopLabelBlock(LabelScopeKind.Filter);

            // begin the catch, clear the exception, we've 
            // already saved it
            _ilg.MarkLabel(endFilter);
            _ilg.BeginCatchBlock(null);
            _ilg.Emit(OpCodes.Pop);
        }
Example #44
0
        /// <summary>
        /// Process an unplugged method.
        /// </summary>
        /// <param name="aMethod">The method to process.</param>
        /// <param name="staticConstructorDependencyRoot">Null if method scanning is not a static constructor. Otherwise, the root node that represents the static constructor being scanned.</param>
        /// <returns>A new ILChunk with ILOpInfos and common attribites loaded. Null if any errors occur.</returns>
        /// <exception cref="System.Exception">
        /// Thrown when an unrecognised operand type is read. Can occur if MSBuild has been 
        /// updated/extended from when the kernel compiler was last updated.
        /// </exception>
        public ILChunk ProcessUnpluggedMethod(MethodBase aMethod, StaticConstructorDependency staticConstructorDependencyRoot = null)
        {
            ILChunk result = new ILChunk()
            {
                Plugged = false,
                Method = aMethod
            };

            //Pre-process common method attributes so we get information such as
            //whether to apply GC or not etc.
            ProcessCommonMethodAttributes(aMethod, result);

            //Get the method body which can then be used to get locals info and
            //IL bytes that are the IL code.
            MethodBody theMethodBody = aMethod.GetMethodBody();

            //Method body for something like [DelegateType].Invoke()
            //  is null
            if (theMethodBody == null)
            {
                //Just return empty method
                return result;
            }

            //For each local variable in this method
            foreach (LocalVariableInfo aLocal in theMethodBody.LocalVariables)
            {
                //Add it to our list of locals with some common information pre-worked out
                LocalVariable localItem = new LocalVariable()
                {
                    sizeOnStackInBytes = Utils.GetNumBytesForType(aLocal.LocalType),
                    isFloat = Utils.IsFloat(aLocal.LocalType),
                    TheType = aLocal.LocalType,
                    isGCManaged = Utils.IsGCManaged(aLocal.LocalType)
                };
                result.LocalVariables.Add(localItem);
            }


            //Used later to store location and length of the cleanup try-finally block
            int CleanUpBlock_TryOffset = 0;
            int CleanUpBlock_TryLength = 0;
            int CleanUpBlock_FinallyOffset = 0;
            int CleanUpBlock_FinallyLength = 0;
            //The "cleanup" block is the finally handler created by the IL reader that
            //calls GC.DecrementRefCount of locals and arguments as-required so that 
            //memory managed by the GC through objects gets freed correctly.
            //The try-section of the cleanup block surrounds all of the main code of the method
            //excluding the final "ret" instruction. In this way, even if an exception occurs, 
            //locals and args still get "cleaned up".
            
            //The IL bytes are the IL code.
            byte[] ILBytes = theMethodBody.GetILAsByteArray();
            //Note: IL offsets are usually calculated as the number of bytes offset from the
            //      start of the method.
            //Note: IL line numbers are IL offsets.

            //The current position in the IL bytes. 
            //This will change throughout the loop below so it always points past
            //all the bytes processed so far.
            int ILBytesPos = 0;
            //The previous position in the IL bytes.
            //This will only change in the loop below after a new IL op is created. In this way,
            //it actually points to the IL bytes position just before the new op is created.
            //That is to say, it points to the IL bytes pos of the start of the new op.
            int PrevILBytesPos = 0;

            //The previous IL op info that was created.
            //This is the latest one that was created as opposed the the one before that.
            //I.e. this is the last ILOpInfo added to the final list of IL op infos.
            ILOpInfo prevInfo = null;

            //Loop through all the IL bytes for this method...
            while (ILBytesPos < ILBytes.Length)
            {
                //The current System.Reflection.Emit.OpCode being processed
                OpCode currOpCode;
                //The unique number that identifies the op code. 
                //This number is also deliberately equivalent to Kernel.Compiler.ILOps.IlOp.OpCodes!
                ushort currOpCodeID = 0;
                //MSIL is saved such that OpIds that only require 1 byte, only use 1 byte!
                //ILBytes encoded as big-endian(?) so high bytes of the op code value (ID) come first
                //So if high byte is set to 0xFE then we need to load the next byte as low byte
                if (ILBytes[ILBytesPos] == 0xFE)
                {
                    currOpCodeID = (ushort)(0xFE00 + (short)ILBytes[ILBytesPos + 1]);
                    ILBytesPos += 2;
                }
                else
                {
                    currOpCodeID = (ushort)ILBytes[ILBytesPos];
                    ILBytesPos++;
                }
                //Load the op code from our pre-constructed list of all op codes
                currOpCode = AllOpCodes[currOpCodeID];

                int operandSize = 0;
                //Operand type tells us the operand size
                //We must:
                // a) Skip over the operand bytes so that we read the next IL op correctly
                // b) Store the operand bytes in the ILOpInfo for later use
                switch(currOpCode.OperandType)
                {
                    case OperandType.InlineBrTarget:
                        operandSize = 4;
                        break;
                    case OperandType.InlineField:
                        operandSize = 4;
                        break;
                    case OperandType.InlineI:
                        operandSize = 4;
                        break;
                    case OperandType.InlineI8:
                        operandSize = 8;
                        break;
                    case OperandType.InlineMethod:
                        operandSize = 4;
                        break;
                    case OperandType.InlineNone:
                        //No operands = no op size
                        break;
                    case OperandType.InlineR:
                        operandSize = 8;
                        break;
                    case OperandType.InlineSig:
                        operandSize = 4;
                        break;
                    case OperandType.InlineString:
                        operandSize = 4;
                        break;
                    case OperandType.InlineSwitch:
                        {
                            int count = Utils.ReadInt32(ILBytes, ILBytesPos);
                            ILBytesPos += 4;
                            operandSize = count * 4;
                        }
                        break;
                    case OperandType.InlineTok:
                        operandSize = 4;
                        break;
                    case OperandType.InlineType:
                        operandSize = 4;
                        break;
                    case OperandType.InlineVar:
                        operandSize = 2;
                        break;
                    case OperandType.ShortInlineBrTarget:
                        operandSize = 1;
                        break;
                    case OperandType.ShortInlineI:
                        operandSize = 1;
                        break;
                    case OperandType.ShortInlineR:
                        operandSize = 4;
                        break;
                    case OperandType.ShortInlineVar:
                        operandSize = 1;
                        break;
                    default:
                        throw new Exception("Unrecognised operand type!");
                }
                
                //Update the previous op with next position now that we
                //  know what that is...
                if (prevInfo != null)
                {
                    prevInfo.NextPosition = PrevILBytesPos;
                }

                //The IL reader pre-loads any methods that should be called by, for example, a call op
                //This was added so that the MethodToCall could be set by the IL reader to inject call ops
                //    - It was going to be a lot harder to try and get the "metadata token bytes" for the 
                //      method to call than to simply "pre-load" the method to call.
                MethodBase methodToCall = null;
                //Value bytes generally contain a constant value to be loaded or the bytes of a metadata token.
                //Metadata tokens can be used to retrieve information such as string literals or method infos
                //from the calling assembly.
                byte[] valueBytes = new byte[operandSize];
                //Don't bother copying 0 bytes...
                if (operandSize > 0)
                {
                    //Copy the bytes...
                    Array.Copy(ILBytes, ILBytesPos, valueBytes, 0, operandSize);

                    //If the op is one where the valueBytes are a metadata token pointing to a method:
                    if ((ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Call ||
                        (ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Calli ||
                        (ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Callvirt ||
                        (ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Ldftn ||
                        (ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Newobj)
                    {
                        //Pre-load the method for reasons described above. 

                        //The metadata token that identifies the method to call in the DLL
                        //It is used to retrieve more information about the method from the DLL
                        int MethodMetadataToken = Utils.ReadInt32(valueBytes, 0);
                        //The method to call retrieved using the metasdata token
                        methodToCall = aMethod.Module.ResolveMethod(MethodMetadataToken);
                    }
                }

                //If the op being processed is a Return op and this method has GC applied:
                if ((ILOps.ILOp.OpCodes)currOpCode.Value == ILOps.ILOp.OpCodes.Ret &&
                    result.ApplyGC)
                {       
                    //We must insert the cleanup block code.

                    //Insert try-finally block around the entire method but just before Ret
                    //The finally block can then do clean-up of local variables and args
                    //1. Insert IL ops for doing locals / args cleanup
                    //2. Add the try/finally block (or just finally block if try block already exists)

                    //We must also consider the fact that just before a "ret" op, the return value is loaded.
                    //Since this cleanup block will wrap that load op, we must add code to store the return value 
                    //at the end of the try block and then re-load the return value after the finally block (but
                    //before the ret op.)

                    //Get a list of all the params to the current method
                    List<Type> allParams = result.Method.GetParameters()
                        .Select(x => x.ParameterType)
                        .ToList();
                    //If it isn't a static method:
                    if (!result.Method.IsStatic)
                    {
                        //The first param is the current instance reference.
                        allParams.Insert(0, result.Method.DeclaringType);
                    }
                    //Only insert the cleanup block if there are some params or locals to clean up.
                    //This is the first of two checks of this condition.
                    if (result.LocalVariables.Count > 0 ||
                        allParams.Count > 0)
                    {
                        //As per above we need to check for return value
                        LocalVariable returnValVariable = null;
                        //Return type of constructor is void, so only check proper methods
                        if(result.Method is MethodInfo)
                        {
                            Type returnType = ((MethodInfo)result.Method).ReturnType;
                            //Void return type = no return value
                            if(returnType != typeof(void))
                            {
                                //Add a new local variable for storing the return value
                                returnValVariable = new LocalVariable()
                                {
                                    isFloat = Utils.IsFloat(returnType),
                                    sizeOnStackInBytes = Utils.GetNumBytesForType(returnType),
                                    TheType = returnType,
                                    isGCManaged = Utils.IsGCManaged(returnType)
                                };
                                result.LocalVariables.Add(returnValVariable);
                                //This will become the penultimate IL op of the try-block
                                //It will immediately follow the op just before ret which 
                                //  will have loaded the return value or, at the very least,
                                //  the top-most item on the stack is the return value
                                //This op stores that return value in our new local variable
                                //  for reload after the finally block has completed.
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Stloc,
                                    Position = PrevILBytesPos++,
                                    NextPosition = PrevILBytesPos,
                                    ValueBytes = BitConverter.GetBytes(result.LocalVariables.IndexOf(returnValVariable))
                                });
                            }
                        }
                        //This becomes the last op of the try-block (and is required to be
                        //  the last op of a try block)
                        result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                        {
                            opCode = OpCodes.Leave_S,
                            Position = PrevILBytesPos++,
                            NextPosition = PrevILBytesPos,
                            ValueBytes = new byte[4]
                        });

                        //Try block length is now the length in IL bytes from start
                        //  (i.e. offset) to start of the current IL op. See above for
                        //  why we use PrevIlBytesPos.
                        CleanUpBlock_TryLength = PrevILBytesPos - CleanUpBlock_TryOffset;
                        //Finally offset is offset to first op of finally block i.e. 
                        //  current IL op position.
                        CleanUpBlock_FinallyOffset = PrevILBytesPos;
                        //Finally length is currently 0 - gets increased later.
                        CleanUpBlock_FinallyLength = 0;

                        //Add cleanup code for each local
                        for (int i = 0; i < result.LocalVariables.Count; i++)
                        {
                            //Clean-up local variables
                            //If the local variable is GC handled:
                            //1. Load the the local
                            //2. Call GC Dec Ref count

                            LocalVariable aVar = result.LocalVariables[i];
                            //Only add cleanup code if the local is actually GC managed.
                            if (Utils.IsGCManaged(aVar.TheType))
                            {
                                if (prevInfo != null)
                                {
                                    prevInfo.NextPosition = PrevILBytesPos;
                                }
                                //Load the local
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Ldloc,
                                    Position = PrevILBytesPos++,
                                    NextPosition = -1,
                                    ValueBytes = BitConverter.GetBytes(i)
                                });
                                prevInfo.NextPosition = PrevILBytesPos;
                                //Decrement the ref count of the local
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Call,
                                    Position = PrevILBytesPos++,
                                    NextPosition = -1,
                                    SetToGCDecRefCountMethod = true
                                });

                                CleanUpBlock_FinallyLength += 2;
                            }
                        }
                        //Add cleanup code for each arg
                        //Dec ref count of all args passed to the method 
                        for (int i = 0; i < allParams.Count; i++)
                        {
                            Type aVarType = allParams[i];
                            //Only add cleanup code if the arg is actually GC managed.
                            if (Utils.IsGCManaged(aVarType))
                            {
                                if (prevInfo != null)
                                {
                                    prevInfo.NextPosition = PrevILBytesPos;
                                }
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Ldarg,
                                    Position = PrevILBytesPos++,
                                    NextPosition = -1,
                                    ValueBytes = BitConverter.GetBytes(i)
                                });
                                prevInfo.NextPosition = PrevILBytesPos;
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Call,
                                    Position = PrevILBytesPos++,
                                    NextPosition = -1,
                                    SetToGCDecRefCountMethod = true
                                });

                                CleanUpBlock_FinallyLength += 2;
                            }
                        }

                        //Locals and args not necessarily of GC managed type
                        //  so we could potentially have cleaned up nothing
                        //This is the second of the two checks to make sure we 
                        //  only add cleanup code if there is something to cleanup
                        if (CleanUpBlock_FinallyLength > 0)
                        {
                            //If there is cleanup code, add the end of the finally block and
                            // reload the return value if necessary.

                            prevInfo.NextPosition = PrevILBytesPos;
                            result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                            {
                                opCode = OpCodes.Endfinally,
                                Position = PrevILBytesPos++,
                                NextPosition = -1
                            });
                            CleanUpBlock_FinallyLength += 1;

                            if (returnValVariable != null)
                            {
                                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                                {
                                    opCode = OpCodes.Ldloc,
                                    Position = PrevILBytesPos++,
                                    NextPosition = PrevILBytesPos,
                                    ValueBytes = BitConverter.GetBytes(result.LocalVariables.IndexOf(returnValVariable))
                                });
                            }
                        }
                        else
                        {
                            //If there was nothing to cleanup, we need to remove 
                            //  the ops and locals etc. that got added earlier.
                            result.ILOpInfos.RemoveAt(result.ILOpInfos.Count - 1);
                            PrevILBytesPos--;

                            if(returnValVariable != null)
                            {
                                result.LocalVariables.Remove(returnValVariable);
                                result.ILOpInfos.RemoveAt(result.ILOpInfos.Count - 1);
                                PrevILBytesPos--;
                            }
                        }
                    }
                }

                if (staticConstructorDependencyRoot != null)
                {
                    //Create our static constructor dependency tree
                    
                    //Each of these ops could try to access a static method or field
                    switch((ILOps.ILOp.OpCodes)currOpCode.Value)
                    {
                        case ILOps.ILOp.OpCodes.Call:
                            //Check if the method to call is static and not a constructor itself
                            //If so, we must add the declaring type's static constructors to the tree
                            {
                                int metadataToken = Utils.ReadInt32(valueBytes, 0);
                                MethodBase methodBaseInf = aMethod.Module.ResolveMethod(metadataToken);
                                if(!(methodBaseInf.IsConstructor || methodBaseInf is ConstructorInfo))
                                {
                                    MethodInfo methodInf = (MethodInfo)methodBaseInf;
                                    ConstructorInfo[] staticConstructors = methodInf.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.Public)
                                                               .Concat(methodInf.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic))
                                                               .ToArray();
                                    if (staticConstructors.Length > 0)
                                    {
                                        ConstructorInfo TheConstructor = staticConstructors[0];
                                        if (staticConstructorDependencyRoot[TheConstructor] == null)
                                        {
                                            staticConstructorDependencyRoot.Children.Add(new StaticConstructorDependency()
                                            {
                                                TheConstructor = TheConstructor
                                            });
                                        }
                                    }
                                }
                            }
                            break;
                        case ILOps.ILOp.OpCodes.Ldsfld:
                        case ILOps.ILOp.OpCodes.Ldsflda:
                        case ILOps.ILOp.OpCodes.Stsfld:
                            {
                                int metadataToken = Utils.ReadInt32(valueBytes, 0);
                                FieldInfo fieldInf = aMethod.Module.ResolveField(metadataToken);
                                ConstructorInfo[] staticConstructors = fieldInf.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.Public)
                                                               .Concat(fieldInf.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic))
                                                               .ToArray();
                                if(staticConstructors.Length > 0)
                                {
                                    ConstructorInfo TheConstructor = staticConstructors[0];
                                    if (staticConstructorDependencyRoot[TheConstructor] == null)
                                    {
                                        staticConstructorDependencyRoot.Children.Add(new StaticConstructorDependency()
                                        {
                                            TheConstructor = TheConstructor
                                        });
                                    }
                                }
                            }
                            break;
                    }
                }

                //Add the IL op
                result.ILOpInfos.Add(prevInfo = new ILOpInfo()
                {
                    opCode = currOpCode,
                    Position = PrevILBytesPos,
                    // Next position set to -1 indicates no next op
                    NextPosition = -1,
                    ValueBytes = valueBytes,
                    MethodToCall = methodToCall
                });

                ILBytesPos += operandSize;
                PrevILBytesPos = ILBytesPos;
            }
            prevInfo.NextPosition = PrevILBytesPos;
            
            //Add the exception handlers (excluding Cleanup try-finally block - see below)
            foreach (ExceptionHandlingClause aClause in theMethodBody.ExceptionHandlingClauses)
            {
                ExceptionHandledBlock exBlock = result.GetExactExceptionHandledBlock(aClause.TryOffset);
                if (exBlock == null)
                {
                    exBlock = new ExceptionHandledBlock();
                    exBlock.Offset = aClause.TryOffset;
                    exBlock.Length = aClause.TryLength;
                    result.ExceptionHandledBlocks.Add(exBlock);
                }

                switch (aClause.Flags)
                {
                    case ExceptionHandlingClauseOptions.Fault:
                    case ExceptionHandlingClauseOptions.Clause:
                        {
                            CatchBlock catchBlock = new CatchBlock()
                            {
                                Offset = aClause.HandlerOffset,
                                Length = aClause.HandlerLength,
                                //Though not used, we may as well set it anyway
                                FilterType = aClause.CatchType
                            };
                            exBlock.CatchBlocks.Add(catchBlock);
                        }
                        break;
                    case ExceptionHandlingClauseOptions.Finally:
                        {
                            FinallyBlock finallyBlock = new FinallyBlock()
                            {
                                Offset = aClause.HandlerOffset,
                                Length = aClause.HandlerLength
                            };
                            exBlock.FinallyBlocks.Add(finallyBlock);
                        }
                        break;
                    default:
                        OutputError(new NotSupportedException("Exception handling clause not supported! Type: " + aClause.Flags.ToString()));
                        break;
                }
            }

            //Add the cleanup try-finally block
            //Only add the block if try-section has non-zero length and
            //  if the finally block has more than just the endfinally op
            if (CleanUpBlock_TryLength != 0 &&
                CleanUpBlock_FinallyLength > 1)
            {
                ExceptionHandledBlock cleanUpTryBlock = new ExceptionHandledBlock()
                {
                    Offset = CleanUpBlock_TryOffset,
                    Length = CleanUpBlock_TryLength
                };
                FinallyBlock cleanupFinallyBlock = new FinallyBlock()
                {
                    Offset = CleanUpBlock_FinallyOffset,
                    Length = CleanUpBlock_FinallyLength,
                };
                cleanUpTryBlock.FinallyBlocks.Add(cleanupFinallyBlock);
                result.ExceptionHandledBlocks.Add(cleanUpTryBlock);
            }
                            
            return result;
        }
Example #45
0
 internal TryCatchEdge(BoundBlock source, BoundBlock body, CatchBlock[] catchBlocks, BoundBlock finallyBlock, BoundBlock endBlock)
     : base(source)
 {
     _body = body;
     _catchBlocks = catchBlocks;
     _finallyBlock = finallyBlock;
     _end = endBlock;
     Connect(source);
 }
		private void DoAddBlock(CatchBlock block)
		{
			DoAddBlock(block.Index, block.Length - 1);	// ditto
		}