Example #1
0
 public FunctionGenerator()
 {
     this.currentFunction = null;
     this.currentBreak = null;
     this.currentContinue = null;
     this.currentExceptionContext = null;
     this.builder = new BlockBuilder();
 }
Example #2
0
 public CatchStatement(Expression exceptionType, string name,
                        AstNode children, TokenPosition position)
     : base(children, position)
 {
     SetName(name);
     this.exceptionType = exceptionType;
     this.context = null;
     this.variable = null;
 }
Example #3
0
        public ExceptionContext(ExceptionContext parentContext)
        {
            // Store parent-child relation.
            this.parentContext = parentContext;
            this.parentFunction = parentContext.parentFunction;
            parentContext.children.Add(this);
            module = parentFunction.GetModule();

            // Initialize more variables.
            this.children = new List<ExceptionContext> ();
            this.blocks = new List<BasicBlock> ();
            this.handlers = new List<Handler> ();
            this.cleanup = null;
        }
Example #4
0
 protected Function(ChelaModule module)
     : base(module)
 {
     this.name = string.Empty;
     this.flags = MemberFlags.Default;
     this.parentScope = null;
     this.basicBlocks = new List<BasicBlock> ();
     this.lexicalScopes = new List<LexicalScope>();
     this.locals = new List<LocalVariable> ();
     this.position = null;
     this.exceptionContext = null;
     this.returnBlock = null;
     this.returningVar = null;
     this.returnValueVar = null;
     this.genericPrototype = GenericPrototype.Empty;
     this.arguments  = null;
 }
Example #5
0
        public ExceptionContext(Function parentFunction)
        {
            // Store parent-child relation.
            this.parentContext = null;
            this.parentFunction = parentFunction;
            module = parentFunction.GetModule();
            if(parentFunction.exceptionContext != null)
                throw new ModuleException("A function only can have one (toplevel) exception context.");

            parentFunction.exceptionContext = this;

            // Initialize more variables.
            this.children = new List<ExceptionContext> ();
            this.blocks = new List<BasicBlock> ();
            this.handlers = new List<Handler> ();
            this.cleanup = null;
        }
Example #6
0
 public void SetContext(ExceptionContext context)
 {
     this.context = context;
 }
Example #7
0
 public FinallyStatement(AstNode children, TokenPosition position)
     : base(position)
 {
     this.children = children;
     this.context = null;
 }
Example #8
0
 private int CountExceptionContexts(ExceptionContext context)
 {
     int ret = context.GetChildrenCount();
     foreach(ExceptionContext subcontext in context.GetChildren())
         ret += CountExceptionContexts(subcontext);
     return ret;
 }
Example #9
0
        internal void SwapExceptionContexts(Function other)
        {
            // Make sure the other end also takes my exception context.
            ExceptionContext newContext = other.exceptionContext;
            if(exceptionContext != null)
            {
                other.exceptionContext = null;
                other.SwapExceptionContexts(this);
            }

            // Use the new exception context.
            exceptionContext = newContext;
            if(newContext != null)
                exceptionContext.UpdateParent(this);
        }
Example #10
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();
        }
Example #11
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;
        }
Example #12
0
 public FunctionSemantic()
 {
     currentExceptionContext = null;
     currentSwitch = null;
 }