Esempio n. 1
0
        public override AstNode Visit(TryStatement node)
        {
            // Begin the node.
            builder.BeginNode(node);

            // Read the substatements.
            AstNode tryNode = node.GetTryStatement();
            AstNode catchList = node.GetCatchList();
            AstNode finalNode = node.GetFinallyStatement();

            // Read the exception context.
            ExceptionContext context = node.GetContext();

            // Create the finally block.
            BasicBlock finalBlock = null;
            if(finalNode != null)
            {
                finalBlock = CreateBasicBlock();
                finalBlock.SetName("finally");
                context.SetCleanup(finalBlock);
            }

            // Create the merge block.
            BasicBlock merge = finalBlock;
            if(merge == null)
            {
                merge = CreateBasicBlock();
                merge.SetName("trymerge");
            }

            // Store the old context.
            ExceptionContext oldContext = currentExceptionContext;
            currentExceptionContext = context;

            // Create the try block.
            BasicBlock tryBlock = CreateBasicBlock();
            tryBlock.SetName("try");
            builder.CreateJmp(tryBlock);
            builder.SetBlock(tryBlock);

            // Process the try statement.
            tryNode.Accept(this);

            // Jump to finally/merge.
            bool tryReturn = builder.IsLastTerminator();
            if(!builder.IsLastTerminator())
                builder.CreateJmp(merge);

            // Restore the context, visit the catch list.
            currentExceptionContext = oldContext;
            AstNode catchNode = catchList;
            while(catchNode != null)
            {
                // Visit it.
                catchNode.Accept(this);

                // Jump to finally/merge.
                if(!builder.IsLastTerminator())
                    builder.CreateJmp(merge);

                // TODO: Avoid "duplicated" catches.
                catchNode = catchNode.GetNext();
            }

            // Visit the finally statement
            if(finalNode != null)
            {
                // Generate the finally block.
                builder.SetBlock(finalBlock);

                // Visit it.
                finalNode.Accept(this);

                // Jump/resume to merge.
                if(builder.IsLastTerminator())
                    Error(finalNode, "finally cannot return.");

                // Create propagate return block.
                BasicBlock propRet = CreateBasicBlock();
                propRet.SetName("propRet");
                builder.CreateJumpResume(propRet);
                builder.SetBlock(propRet);

                // Find the parent return.
                BasicBlock parentRetBlock = null;
                ExceptionContext parentContext = context.GetParentContext();
                while(parentContext != null)
                {
                    parentRetBlock = parentContext.GetCleanup();
                    if(parentRetBlock != null)
                        break;
                    parentContext = parentContext.GetParentContext();
                }

                // Couldn't find a parent cleanup, return.
                if(parentRetBlock == null)
                    parentRetBlock = currentFunction.ReturnBlock;

                // If try returns and theres not catch, just return.
                if(tryReturn && catchNode == null)
                {
                    builder.CreateJmp(parentRetBlock);
                    AstNode next = node.GetNext();
                    if(next != null)
                        Warning(next, "unreachable code detected.");
                    node.SetNext(null);
                }
                else
                {
                    // Merge with the other blocks.
                    merge = CreateBasicBlock();
                    merge.SetName("trymerge");

                    // Return/finally or merge.
                    builder.CreateLoadLocal(currentFunction.ReturningVar);
                    builder.CreateBr(parentRetBlock, merge);
                }
            }

            // Remove unused code.
            if(merge.GetPredsCount() == 0)
            {
                if(node.GetNext() != null)
                    Warning(node, "detected unreachable code at {0}", node.GetNext().GetPosition());
                node.SetNext(null);
                merge.Destroy();
            }
            else
            {
                // Continue without try.
                builder.SetBlock(merge);
            }

            return builder.EndNode();
        }
Esempio n. 2
0
        public override AstNode Visit(TryStatement node)
        {
            // Visit the try clause.
            AstNode tryStatement = node.GetTryStatement();
            tryStatement.Accept(this);

            // Visit the catch clause.
            VisitList(node.GetCatchList());

            // Visit the finally clause.
            AstNode finallyStament = node.GetFinallyStatement();
            if(finallyStament != null)
                finallyStament.Accept(this);

            return node;
        }
Esempio n. 3
0
        public override AstNode Visit(TryStatement node)
        {
            // Read the substatements.
            AstNode tryNode = node.GetTryStatement();
            AstNode catchList = node.GetCatchList();
            AstNode finalNode = node.GetFinallyStatement();

            // Create the exception context.
            ExceptionContext context;
            if(currentExceptionContext != null)
                context = new ExceptionContext(currentExceptionContext);
            else
                context = new ExceptionContext(currentFunction);
            node.SetContext(context);

            // Store the old context and process the try statement.
            ExceptionContext oldContext = currentExceptionContext;
            currentExceptionContext = context;
            tryNode.Accept(this);

            // Restore the context, visit the catch list.
            currentExceptionContext = oldContext;
            AstNode catchNode = catchList;
            while(catchNode != null)
            {
                // Set the exception context.
                CatchStatement catchStmnt = (CatchStatement)catchNode;
                catchStmnt.SetContext(context);

                // Visit it.
                catchStmnt.Accept(this);

                // TODO: Avoid "duplicated" catches.
                catchNode = catchNode.GetNext();
            }

            // Visit the finally statement
            if(finalNode != null)
            {
                // Set the exception context.
                FinallyStatement finalStmnt = (FinallyStatement)finalNode;
                finalStmnt.SetContext(context);

                // Visit it.
                finalStmnt.Accept(this);
            }

            return node;
        }